mirror of
https://github.com/webmproject/libwebp.git
synced 2025-12-24 14:06:27 +01:00
apply clang-format
(Debian clang-format version 19.1.7 (3+build4)) with `--style=Google`. Manual changes: * clang-format disabled around macros with stringification (mostly assembly) * some inline assembly strings were adjusted to avoid awkward line breaks * trailing commas, `//` or suffixes (`ull`) added to help array formatting * thread_utils.c: parameter comments were changed to the more common /*...=*/ style to improve formatting The automatically generated code under swig/ was skipped. Bug: 433996651 Change-Id: Iea3f24160d78d2a2653971cdf13fa932e47ff1b3
This commit is contained in:
@@ -57,8 +57,8 @@ static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int FramesAreSimilar(const uint8_t* const rgba1,
|
static int FramesAreSimilar(const uint8_t* const rgba1,
|
||||||
const uint8_t* const rgba2,
|
const uint8_t* const rgba2, int width, int height,
|
||||||
int width, int height, int max_allowed_diff) {
|
int max_allowed_diff) {
|
||||||
int i, j;
|
int i, j;
|
||||||
assert(max_allowed_diff > 0);
|
assert(max_allowed_diff > 0);
|
||||||
for (j = 0; j < height; ++j) {
|
for (j = 0; j < height; ++j) {
|
||||||
@@ -120,8 +120,7 @@ static int CompareBackgroundColor(uint32_t bg1, uint32_t bg2, int premultiply) {
|
|||||||
if (alpha1 == 0 && alpha2 == 0) return 1;
|
if (alpha1 == 0 && alpha2 == 0) return 1;
|
||||||
}
|
}
|
||||||
if (bg1 != bg2) {
|
if (bg1 != bg2) {
|
||||||
fprintf(stderr, "Background color mismatch: 0x%08x vs 0x%08x\n",
|
fprintf(stderr, "Background color mismatch: 0x%08x vs 0x%08x\n", bg1, bg2);
|
||||||
bg1, bg2);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -131,8 +130,7 @@ static int CompareBackgroundColor(uint32_t bg1, uint32_t bg2, int premultiply) {
|
|||||||
// is OK for other aspects like offsets, dispose/blend method to vary.
|
// is OK for other aspects like offsets, dispose/blend method to vary.
|
||||||
static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
||||||
const AnimatedImage* const img2,
|
const AnimatedImage* const img2,
|
||||||
int premultiply,
|
int premultiply, double min_psnr) {
|
||||||
double min_psnr) {
|
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
const int is_multi_frame_image = (img1->num_frames > 1);
|
const int is_multi_frame_image = (img1->num_frames > 1);
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@@ -141,8 +139,8 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
|||||||
"Canvas width mismatch");
|
"Canvas width mismatch");
|
||||||
ok &= CompareValues(img1->canvas_height, img2->canvas_height,
|
ok &= CompareValues(img1->canvas_height, img2->canvas_height,
|
||||||
"Canvas height mismatch");
|
"Canvas height mismatch");
|
||||||
ok &= CompareValues(img1->num_frames, img2->num_frames,
|
ok &=
|
||||||
"Frame count mismatch");
|
CompareValues(img1->num_frames, img2->num_frames, "Frame count mismatch");
|
||||||
if (!ok) return 0; // These are fatal failures, can't proceed.
|
if (!ok) return 0; // These are fatal failures, can't proceed.
|
||||||
|
|
||||||
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
||||||
@@ -178,8 +176,8 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
|||||||
premultiply, &max_diff, &psnr);
|
premultiply, &max_diff, &psnr);
|
||||||
if (min_psnr > 0.) {
|
if (min_psnr > 0.) {
|
||||||
if (psnr < min_psnr) {
|
if (psnr < min_psnr) {
|
||||||
fprintf(stderr, "Frame #%d, psnr = %.2lf (min_psnr = %f)\n", i,
|
fprintf(stderr, "Frame #%d, psnr = %.2lf (min_psnr = %f)\n", i, psnr,
|
||||||
psnr, min_psnr);
|
min_psnr);
|
||||||
ok = 0;
|
ok = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -199,7 +197,8 @@ static void Help(void) {
|
|||||||
printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
|
printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
|
||||||
printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
|
printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
|
||||||
printf(" premultiplied before comparison\n");
|
printf(" premultiplied before comparison\n");
|
||||||
printf(" -max_diff <int> ..... maximum allowed difference per channel\n"
|
printf(
|
||||||
|
" -max_diff <int> ..... maximum allowed difference per channel\n"
|
||||||
" between corresponding pixels in subsequent\n"
|
" between corresponding pixels in subsequent\n"
|
||||||
" frames\n");
|
" frames\n");
|
||||||
printf(" -h .................. this help\n");
|
printf(" -h .................. this help\n");
|
||||||
@@ -217,7 +216,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
int premultiply = 1;
|
int premultiply = 1;
|
||||||
int max_diff = 0;
|
int max_diff = 0;
|
||||||
int i, c;
|
int i, c;
|
||||||
const char* files[2] = { NULL, NULL };
|
const char* files[2] = {NULL, NULL};
|
||||||
AnimatedImage images[2];
|
AnimatedImage images[2];
|
||||||
|
|
||||||
INIT_WARGV(argc, argv);
|
INIT_WARGV(argc, argv);
|
||||||
@@ -253,9 +252,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
GetAnimatedImageVersions(&dec_version, &demux_version);
|
GetAnimatedImageVersions(&dec_version, &demux_version);
|
||||||
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
||||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
(dec_version >> 0) & 0xff,
|
(dec_version >> 0) & 0xff, (demux_version >> 16) & 0xff,
|
||||||
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
(demux_version >> 8) & 0xff, (demux_version >> 0) & 0xff);
|
||||||
(demux_version >> 0) & 0xff);
|
|
||||||
FREE_WARGV_AND_RETURN(0);
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else {
|
} else {
|
||||||
if (!got_input1) {
|
if (!got_input1) {
|
||||||
@@ -278,7 +276,6 @@ int main(int argc, const char* argv[]) {
|
|||||||
FREE_WARGV_AND_RETURN(return_code);
|
FREE_WARGV_AND_RETURN(return_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!got_input2) {
|
if (!got_input2) {
|
||||||
Help();
|
Help();
|
||||||
FREE_WARGV_AND_RETURN(return_code);
|
FREE_WARGV_AND_RETURN(return_code);
|
||||||
@@ -301,8 +298,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CompareAnimatedImagePair(&images[0], &images[1],
|
if (!CompareAnimatedImagePair(&images[0], &images[1], premultiply,
|
||||||
premultiply, min_psnr)) {
|
min_psnr)) {
|
||||||
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
|
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
|
||||||
(const W_CHAR*)files[1]);
|
(const W_CHAR*)files[1]);
|
||||||
return_code = 1;
|
return_code = 1;
|
||||||
@@ -311,7 +308,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
(const W_CHAR*)files[1]);
|
(const W_CHAR*)files[1]);
|
||||||
return_code = 0;
|
return_code = 0;
|
||||||
}
|
}
|
||||||
End:
|
End:
|
||||||
ClearAnimatedImage(&images[0]);
|
ClearAnimatedImage(&images[0]);
|
||||||
ClearAnimatedImage(&images[1]);
|
ClearAnimatedImage(&images[1]);
|
||||||
FREE_WARGV_AND_RETURN(return_code);
|
FREE_WARGV_AND_RETURN(return_code);
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ static void Help(void) {
|
|||||||
printf("Usage: anim_dump [options] files...\n");
|
printf("Usage: anim_dump [options] files...\n");
|
||||||
printf("\nOptions:\n");
|
printf("\nOptions:\n");
|
||||||
printf(" -folder <string> .... dump folder (default: '.')\n");
|
printf(" -folder <string> .... dump folder (default: '.')\n");
|
||||||
printf(" -prefix <string> .... prefix for dumped frames "
|
printf(
|
||||||
|
" -prefix <string> .... prefix for dumped frames "
|
||||||
"(default: 'dump_')\n");
|
"(default: 'dump_')\n");
|
||||||
printf(" -tiff ............... save frames as TIFF\n");
|
printf(" -tiff ............... save frames as TIFF\n");
|
||||||
printf(" -pam ................ save frames as PAM\n");
|
printf(" -pam ................ save frames as PAM\n");
|
||||||
@@ -82,17 +83,16 @@ int main(int argc, const char* argv[]) {
|
|||||||
GetAnimatedImageVersions(&dec_version, &demux_version);
|
GetAnimatedImageVersions(&dec_version, &demux_version);
|
||||||
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
||||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
(dec_version >> 0) & 0xff,
|
(dec_version >> 0) & 0xff, (demux_version >> 16) & 0xff,
|
||||||
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
(demux_version >> 8) & 0xff, (demux_version >> 0) & 0xff);
|
||||||
(demux_version >> 0) & 0xff);
|
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
AnimatedImage image;
|
AnimatedImage image;
|
||||||
const W_CHAR* const file = GET_WARGV(argv, c);
|
const W_CHAR* const file = GET_WARGV(argv, c);
|
||||||
memset(&image, 0, sizeof(image));
|
memset(&image, 0, sizeof(image));
|
||||||
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n",
|
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n", file, dump_folder, prefix,
|
||||||
file, dump_folder, prefix, suffix);
|
suffix);
|
||||||
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
|
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
|
||||||
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
|
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
|
||||||
error = 1;
|
error = 1;
|
||||||
@@ -113,8 +113,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
buffer.u.RGBA.rgba = image.frames[i].rgba;
|
buffer.u.RGBA.rgba = image.frames[i].rgba;
|
||||||
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
|
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
|
||||||
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
|
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
|
||||||
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s",
|
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s", dump_folder,
|
||||||
dump_folder, prefix, i, suffix);
|
prefix, i, suffix);
|
||||||
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
|
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
|
||||||
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
|
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
|
||||||
error = 1;
|
error = 1;
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ static const int kNumChannels = 4;
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_GIF)
|
#if defined(WEBP_HAVE_GIF)
|
||||||
// Returns true if the frame covers the full canvas.
|
// Returns true if the frame covers the full canvas.
|
||||||
static int IsFullFrame(int width, int height,
|
static int IsFullFrame(int width, int height, int canvas_width,
|
||||||
int canvas_width, int canvas_height) {
|
int canvas_height) {
|
||||||
return (width == canvas_width && height == canvas_height);
|
return (width == canvas_width && height == canvas_height);
|
||||||
}
|
}
|
||||||
#endif // WEBP_HAVE_GIF
|
#endif // WEBP_HAVE_GIF
|
||||||
@@ -95,8 +95,8 @@ void ClearAnimatedImage(AnimatedImage* const image) {
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_GIF)
|
#if defined(WEBP_HAVE_GIF)
|
||||||
// Clear the canvas to transparent.
|
// Clear the canvas to transparent.
|
||||||
static void ZeroFillCanvas(uint8_t* rgba,
|
static void ZeroFillCanvas(uint8_t* rgba, uint32_t canvas_width,
|
||||||
uint32_t canvas_width, uint32_t canvas_height) {
|
uint32_t canvas_height) {
|
||||||
memset(rgba, 0, canvas_width * kNumChannels * canvas_height);
|
memset(rgba, 0, canvas_width * kNumChannels * canvas_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,16 +113,16 @@ static void ZeroFillFrameRect(uint8_t* rgba, int rgba_stride, int x_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy width * height pixels from 'src' to 'dst'.
|
// Copy width * height pixels from 'src' to 'dst'.
|
||||||
static void CopyCanvas(const uint8_t* src, uint8_t* dst,
|
static void CopyCanvas(const uint8_t* src, uint8_t* dst, uint32_t width,
|
||||||
uint32_t width, uint32_t height) {
|
uint32_t height) {
|
||||||
assert(src != NULL && dst != NULL);
|
assert(src != NULL && dst != NULL);
|
||||||
memcpy(dst, src, width * kNumChannels * height);
|
memcpy(dst, src, width * kNumChannels * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy pixels in the given rectangle from 'src' to 'dst' honoring the 'stride'.
|
// Copy pixels in the given rectangle from 'src' to 'dst' honoring the 'stride'.
|
||||||
static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
||||||
int x_offset, int y_offset,
|
int x_offset, int y_offset, int width,
|
||||||
int width, int height) {
|
int height) {
|
||||||
int j;
|
int j;
|
||||||
const int width_in_bytes = width * kNumChannels;
|
const int width_in_bytes = width * kNumChannels;
|
||||||
const size_t offset = y_offset * stride + x_offset * kNumChannels;
|
const size_t offset = y_offset * stride + x_offset * kNumChannels;
|
||||||
@@ -138,8 +138,8 @@ static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
|||||||
#endif // WEBP_HAVE_GIF
|
#endif // WEBP_HAVE_GIF
|
||||||
|
|
||||||
// Canonicalize all transparent pixels to transparent black to aid comparison.
|
// Canonicalize all transparent pixels to transparent black to aid comparison.
|
||||||
static void CleanupTransparentPixels(uint32_t* rgba,
|
static void CleanupTransparentPixels(uint32_t* rgba, uint32_t width,
|
||||||
uint32_t width, uint32_t height) {
|
uint32_t height) {
|
||||||
const uint32_t* const rgba_end = rgba + width * height;
|
const uint32_t* const rgba_end = rgba + width * height;
|
||||||
while (rgba < rgba_end) {
|
while (rgba < rgba_end) {
|
||||||
const uint8_t alpha = (*rgba >> 24) & 0xff;
|
const uint8_t alpha = (*rgba >> 24) & 0xff;
|
||||||
@@ -152,8 +152,8 @@ static void CleanupTransparentPixels(uint32_t* rgba,
|
|||||||
|
|
||||||
// Dump frame to a PAM file. Returns true on success.
|
// Dump frame to a PAM file. Returns true on success.
|
||||||
static int DumpFrame(const char filename[], const char dump_folder[],
|
static int DumpFrame(const char filename[], const char dump_folder[],
|
||||||
uint32_t frame_num, const uint8_t rgba[],
|
uint32_t frame_num, const uint8_t rgba[], int canvas_width,
|
||||||
int canvas_width, int canvas_height) {
|
int canvas_height) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
size_t max_len;
|
size_t max_len;
|
||||||
int y;
|
int y;
|
||||||
@@ -166,8 +166,8 @@ static int DumpFrame(const char filename[], const char dump_folder[],
|
|||||||
|
|
||||||
base_name = WSTRRCHR(filename, '/');
|
base_name = WSTRRCHR(filename, '/');
|
||||||
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
|
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
|
||||||
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name)
|
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name) + strlen("_frame_") +
|
||||||
+ strlen("_frame_") + strlen(".pam") + 8;
|
strlen(".pam") + 8;
|
||||||
file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name));
|
file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name));
|
||||||
if (file_name == NULL) goto End;
|
if (file_name == NULL) goto End;
|
||||||
|
|
||||||
@@ -183,7 +183,8 @@ static int DumpFrame(const char filename[], const char dump_folder[],
|
|||||||
ok = 0;
|
ok = 0;
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n"
|
if (fprintf(f,
|
||||||
|
"P7\nWIDTH %d\nHEIGHT %d\n"
|
||||||
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
|
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
|
||||||
canvas_width, canvas_height) < 0) {
|
canvas_width, canvas_height) < 0) {
|
||||||
WFPRINTF(stderr, "Write error for file %s\n", file_name);
|
WFPRINTF(stderr, "Write error for file %s\n", file_name);
|
||||||
@@ -198,7 +199,7 @@ static int DumpFrame(const char filename[], const char dump_folder[],
|
|||||||
row += canvas_width * kNumChannels;
|
row += canvas_width * kNumChannels;
|
||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
End:
|
End:
|
||||||
if (f != NULL) fclose(f);
|
if (f != NULL) fclose(f);
|
||||||
WebPFree(file_name);
|
WebPFree(file_name);
|
||||||
return ok;
|
return ok;
|
||||||
@@ -266,8 +267,8 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
image->canvas_width * kNumChannels * image->canvas_height);
|
image->canvas_width * kNumChannels * image->canvas_height);
|
||||||
|
|
||||||
// Needed only because we may want to compare with GIF later.
|
// Needed only because we may want to compare with GIF later.
|
||||||
CleanupTransparentPixels((uint32_t*)curr_rgba,
|
CleanupTransparentPixels((uint32_t*)curr_rgba, image->canvas_width,
|
||||||
image->canvas_width, image->canvas_height);
|
image->canvas_height);
|
||||||
|
|
||||||
if (dump_frames && dump_ok) {
|
if (dump_frames && dump_ok) {
|
||||||
dump_ok = DumpFrame(filename, dump_folder, frame_index, curr_rgba,
|
dump_ok = DumpFrame(filename, dump_folder, frame_index, curr_rgba,
|
||||||
@@ -283,7 +284,7 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
ok = dump_ok;
|
ok = dump_ok;
|
||||||
if (ok) image->format = ANIM_WEBP;
|
if (ok) image->format = ANIM_WEBP;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
WebPAnimDecoderDelete(dec);
|
WebPAnimDecoderDelete(dec);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -303,12 +304,11 @@ static int IsGIF(const WebPData* const data) {
|
|||||||
|
|
||||||
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
||||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
#define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_PREREQ(maj, min) \
|
#define LOCAL_GIF_PREREQ(maj, min) (LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
||||||
(LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
|
||||||
#else
|
#else
|
||||||
# define LOCAL_GIF_VERSION 0
|
#define LOCAL_GIF_VERSION 0
|
||||||
# define LOCAL_GIF_PREREQ(maj, min) 0
|
#define LOCAL_GIF_PREREQ(maj, min) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !LOCAL_GIF_PREREQ(5, 0)
|
#if !LOCAL_GIF_PREREQ(5, 0)
|
||||||
@@ -357,8 +357,8 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
|
|||||||
for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
|
for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
|
||||||
ExtensionBlock* ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
|
ExtensionBlock* ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
|
||||||
if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
|
if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
|
||||||
return DGifExtensionToGCB(
|
return DGifExtensionToGCB(ep->ByteCount, (const GifByteType*)ep->Bytes,
|
||||||
ep->ByteCount, (const GifByteType*)ep->Bytes, gcb);
|
gcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GIF_ERROR;
|
return GIF_ERROR;
|
||||||
@@ -377,12 +377,12 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
|
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
|
||||||
const DecodedFrame* const prev_frame,
|
const DecodedFrame* const prev_frame, int canvas_width,
|
||||||
int canvas_width, int canvas_height) {
|
int canvas_height) {
|
||||||
if (prev_frame == NULL) return 1;
|
if (prev_frame == NULL) return 1;
|
||||||
if (prev_dispose == DISPOSE_BACKGROUND) {
|
if (prev_dispose == DISPOSE_BACKGROUND) {
|
||||||
if (IsFullFrame(prev_desc->Width, prev_desc->Height,
|
if (IsFullFrame(prev_desc->Width, prev_desc->Height, canvas_width,
|
||||||
canvas_width, canvas_height)) {
|
canvas_height)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (prev_frame->is_key_frame) return 1;
|
if (prev_frame->is_key_frame) return 1;
|
||||||
@@ -403,14 +403,12 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
|
|||||||
if (transparent_index != NO_TRANSPARENT_COLOR &&
|
if (transparent_index != NO_TRANSPARENT_COLOR &&
|
||||||
gif->SBackGroundColor == transparent_index) {
|
gif->SBackGroundColor == transparent_index) {
|
||||||
return 0x00000000; // Special case: transparent black.
|
return 0x00000000; // Special case: transparent black.
|
||||||
} else if (color_map == NULL || color_map->Colors == NULL
|
} else if (color_map == NULL || color_map->Colors == NULL ||
|
||||||
|| gif->SBackGroundColor >= color_map->ColorCount) {
|
gif->SBackGroundColor >= color_map->ColorCount) {
|
||||||
return 0xffffffff; // Invalid: assume white.
|
return 0xffffffff; // Invalid: assume white.
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
|
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
|
||||||
return (0xffu << 24) |
|
return (0xffu << 24) | (color.Red << 16) | (color.Green << 8) |
|
||||||
(color.Red << 16) |
|
|
||||||
(color.Green << 8) |
|
|
||||||
(color.Blue << 0);
|
(color.Blue << 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,11 +433,10 @@ static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
|
|||||||
(eb1->ByteCount == 11) &&
|
(eb1->ByteCount == 11) &&
|
||||||
(!memcmp(signature, "NETSCAPE2.0", 11) ||
|
(!memcmp(signature, "NETSCAPE2.0", 11) ||
|
||||||
!memcmp(signature, "ANIMEXTS1.0", 11));
|
!memcmp(signature, "ANIMEXTS1.0", 11));
|
||||||
if (signature_is_ok &&
|
if (signature_is_ok && eb2->Function == CONTINUE_EXT_FUNC_CODE &&
|
||||||
eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 &&
|
eb2->ByteCount >= 3 && eb2->Bytes[0] == 1) {
|
||||||
eb2->Bytes[0] == 1) {
|
const uint32_t extra_loop =
|
||||||
const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) +
|
((uint32_t)(eb2->Bytes[2]) << 8) + ((uint32_t)(eb2->Bytes[1]) << 0);
|
||||||
((uint32_t)(eb2->Bytes[1]) << 0);
|
|
||||||
return (extra_loop > 0) ? extra_loop + 1 : 0;
|
return (extra_loop > 0) ? extra_loop + 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -535,8 +532,8 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
image->canvas_height = (uint32_t)gif->SHeight;
|
image->canvas_height = (uint32_t)gif->SHeight;
|
||||||
if (image->canvas_width > MAX_CANVAS_SIZE ||
|
if (image->canvas_width > MAX_CANVAS_SIZE ||
|
||||||
image->canvas_height > MAX_CANVAS_SIZE) {
|
image->canvas_height > MAX_CANVAS_SIZE) {
|
||||||
fprintf(stderr, "Invalid canvas dimension: %d x %d\n",
|
fprintf(stderr, "Invalid canvas dimension: %d x %d\n", image->canvas_width,
|
||||||
image->canvas_width, image->canvas_height);
|
image->canvas_height);
|
||||||
DGifCloseFile(gif, NULL);
|
DGifCloseFile(gif, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -611,11 +608,9 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
CopyCanvas(prev_rgba, curr_rgba, canvas_width, canvas_height);
|
CopyCanvas(prev_rgba, curr_rgba, canvas_width, canvas_height);
|
||||||
|
|
||||||
// Dispose previous frame rectangle.
|
// Dispose previous frame rectangle.
|
||||||
prev_frame_disposed =
|
prev_frame_disposed = (prev_gcb.DisposalMode == DISPOSE_BACKGROUND ||
|
||||||
(prev_gcb.DisposalMode == DISPOSE_BACKGROUND ||
|
|
||||||
prev_gcb.DisposalMode == DISPOSE_PREVIOUS);
|
prev_gcb.DisposalMode == DISPOSE_PREVIOUS);
|
||||||
curr_frame_opaque =
|
curr_frame_opaque = (curr_gcb.TransparentColor == NO_TRANSPARENT_COLOR);
|
||||||
(curr_gcb.TransparentColor == NO_TRANSPARENT_COLOR);
|
|
||||||
prev_frame_completely_covered =
|
prev_frame_completely_covered =
|
||||||
curr_frame_opaque &&
|
curr_frame_opaque &&
|
||||||
CoversFrameGIF(&curr_gif_image->ImageDesc, prev_desc);
|
CoversFrameGIF(&curr_gif_image->ImageDesc, prev_desc);
|
||||||
@@ -643,9 +638,9 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
uint8_t* const src_frame_rgba =
|
uint8_t* const src_frame_rgba =
|
||||||
image->frames[src_frame_num].rgba;
|
image->frames[src_frame_num].rgba;
|
||||||
CopyFrameRectangle(src_frame_rgba, curr_rgba,
|
CopyFrameRectangle(src_frame_rgba, curr_rgba,
|
||||||
canvas_width_in_bytes,
|
canvas_width_in_bytes, prev_desc->Left,
|
||||||
prev_desc->Left, prev_desc->Top,
|
prev_desc->Top, prev_desc->Width,
|
||||||
prev_desc->Width, prev_desc->Height);
|
prev_desc->Height);
|
||||||
} else {
|
} else {
|
||||||
// Source canvas doesn't exist. So clear previous frame
|
// Source canvas doesn't exist. So clear previous frame
|
||||||
// rectangle to background.
|
// rectangle to background.
|
||||||
@@ -670,8 +665,8 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dump_frames) {
|
if (dump_frames) {
|
||||||
if (!DumpFrame(filename, dump_folder, i, curr_rgba,
|
if (!DumpFrame(filename, dump_folder, i, curr_rgba, canvas_width,
|
||||||
canvas_width, canvas_height)) {
|
canvas_height)) {
|
||||||
DGifCloseFile(gif, NULL);
|
DGifCloseFile(gif, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -695,7 +690,8 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
(void)image;
|
(void)image;
|
||||||
(void)dump_frames;
|
(void)dump_frames;
|
||||||
(void)dump_folder;
|
(void)dump_folder;
|
||||||
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
|
fprintf(stderr,
|
||||||
|
"GIF support not compiled. Please install the libgif-dev "
|
||||||
"package before building.\n");
|
"package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -718,8 +714,8 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsWebP(&webp_data)) {
|
if (IsWebP(&webp_data)) {
|
||||||
ok = ReadAnimatedWebP(filename, &webp_data, image, dump_frames,
|
ok =
|
||||||
dump_folder);
|
ReadAnimatedWebP(filename, &webp_data, image, dump_frames, dump_folder);
|
||||||
} else if (IsGIF(&webp_data)) {
|
} else if (IsGIF(&webp_data)) {
|
||||||
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
|
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
|
||||||
} else {
|
} else {
|
||||||
@@ -763,8 +759,7 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
|
|||||||
// premultiply R/G/B channels with alpha value
|
// premultiply R/G/B channels with alpha value
|
||||||
for (k = 0; k < kAlphaChannel; ++k) {
|
for (k = 0; k < kAlphaChannel; ++k) {
|
||||||
Accumulate(rgba1[offset + k] * alpha1 / 255.,
|
Accumulate(rgba1[offset + k] * alpha1 / 255.,
|
||||||
rgba2[offset + k] * alpha2 / 255.,
|
rgba2[offset + k] * alpha2 / 255., &f_max_diff, &sse);
|
||||||
&f_max_diff, &sse);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum { ANIM_GIF, ANIM_WEBP } AnimatedFileFormat;
|
||||||
ANIM_GIF,
|
|
||||||
ANIM_WEBP
|
|
||||||
} AnimatedFileFormat;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t* rgba; // Decoded and reconstructed full frame.
|
uint8_t* rgba; // Decoded and reconstructed full frame.
|
||||||
|
|||||||
206
examples/cwebp.c
206
examples/cwebp.c
@@ -66,12 +66,12 @@ static int ReadYUV(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
pic->use_argb = 0;
|
pic->use_argb = 0;
|
||||||
if (!WebPPictureAlloc(pic)) return 0;
|
if (!WebPPictureAlloc(pic)) return 0;
|
||||||
ImgIoUtilCopyPlane(data, pic->width, pic->y, pic->y_stride,
|
ImgIoUtilCopyPlane(data, pic->width, pic->y, pic->y_stride, pic->width,
|
||||||
pic->width, pic->height);
|
pic->height);
|
||||||
ImgIoUtilCopyPlane(data + y_plane_size, uv_width,
|
ImgIoUtilCopyPlane(data + y_plane_size, uv_width, pic->u, pic->uv_stride,
|
||||||
pic->u, pic->uv_stride, uv_width, uv_height);
|
uv_width, uv_height);
|
||||||
ImgIoUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width,
|
ImgIoUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width, pic->v,
|
||||||
pic->v, pic->uv_stride, uv_width, uv_height);
|
pic->uv_stride, uv_width, uv_height);
|
||||||
return use_argb ? WebPPictureYUVAToARGB(pic) : 1;
|
return use_argb ? WebPPictureYUVAToARGB(pic) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
|||||||
// If image size is specified, infer it as YUV format.
|
// If image size is specified, infer it as YUV format.
|
||||||
ok = ReadYUV(data, data_size, pic);
|
ok = ReadYUV(data, data_size, pic);
|
||||||
}
|
}
|
||||||
End:
|
End:
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
||||||
(const W_CHAR*)filename);
|
(const W_CHAR*)filename);
|
||||||
@@ -168,8 +168,8 @@ static void PrintValues(const int values[4]) {
|
|||||||
|
|
||||||
static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
|
static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
|
||||||
const char* const description) {
|
const char* const description) {
|
||||||
fprintf(stderr, "Lossless-%s compressed size: %d bytes\n",
|
fprintf(stderr, "Lossless-%s compressed size: %d bytes\n", description,
|
||||||
description, stats->lossless_size);
|
stats->lossless_size);
|
||||||
fprintf(stderr, " * Header size: %d bytes, image data size: %d\n",
|
fprintf(stderr, " * Header size: %d bytes, image data size: %d\n",
|
||||||
stats->lossless_hdr_size, stats->lossless_data_size);
|
stats->lossless_hdr_size, stats->lossless_data_size);
|
||||||
if (stats->lossless_features) {
|
if (stats->lossless_features) {
|
||||||
@@ -209,8 +209,7 @@ static void PrintExtraInfoLossless(const WebPPicture* const pic,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
||||||
int full_details,
|
int full_details, const char* const file_name) {
|
||||||
const char* const file_name) {
|
|
||||||
const WebPAuxStats* const stats = pic->stats;
|
const WebPAuxStats* const stats = pic->stats;
|
||||||
if (short_output) {
|
if (short_output) {
|
||||||
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
|
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
|
||||||
@@ -220,24 +219,24 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
|||||||
const int num_skip = stats->block_count[2];
|
const int num_skip = stats->block_count[2];
|
||||||
const int total = num_i4 + num_i16;
|
const int total = num_i4 + num_i16;
|
||||||
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name);
|
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name);
|
||||||
fprintf(stderr, "Dimension: %d x %d%s\n",
|
fprintf(stderr, "Dimension: %d x %d%s\n", pic->width, pic->height,
|
||||||
pic->width, pic->height,
|
|
||||||
stats->alpha_data_size ? " (with alpha)" : "");
|
stats->alpha_data_size ? " (with alpha)" : "");
|
||||||
fprintf(stderr, "Output: "
|
fprintf(stderr,
|
||||||
|
"Output: "
|
||||||
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n"
|
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n"
|
||||||
" (%.2f bpp)\n",
|
" (%.2f bpp)\n",
|
||||||
stats->coded_size,
|
stats->coded_size, stats->PSNR[0], stats->PSNR[1], stats->PSNR[2],
|
||||||
stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3],
|
stats->PSNR[3], 8.f * stats->coded_size / pic->width / pic->height);
|
||||||
8.f * stats->coded_size / pic->width / pic->height);
|
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
int totals[4] = { 0, 0, 0, 0 };
|
int totals[4] = {0, 0, 0, 0};
|
||||||
fprintf(stderr, "block count: intra4: %6d (%.2f%%)\n"
|
fprintf(stderr,
|
||||||
|
"block count: intra4: %6d (%.2f%%)\n"
|
||||||
" intra16: %6d (%.2f%%)\n"
|
" intra16: %6d (%.2f%%)\n"
|
||||||
" skipped: %6d (%.2f%%)\n",
|
" skipped: %6d (%.2f%%)\n",
|
||||||
num_i4, 100.f * num_i4 / total,
|
num_i4, 100.f * num_i4 / total, num_i16, 100.f * num_i16 / total,
|
||||||
num_i16, 100.f * num_i16 / total,
|
|
||||||
num_skip, 100.f * num_skip / total);
|
num_skip, 100.f * num_skip / total);
|
||||||
fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n"
|
fprintf(stderr,
|
||||||
|
"bytes used: header: %6d (%.1f%%)\n"
|
||||||
" mode-partition: %6d (%.1f%%)\n",
|
" mode-partition: %6d (%.1f%%)\n",
|
||||||
stats->header_bytes[0],
|
stats->header_bytes[0],
|
||||||
100.f * stats->header_bytes[0] / stats->coded_size,
|
100.f * stats->header_bytes[0] / stats->coded_size,
|
||||||
@@ -247,7 +246,8 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
|||||||
fprintf(stderr, " transparency: %6d (%.1f dB)\n",
|
fprintf(stderr, " transparency: %6d (%.1f dB)\n",
|
||||||
stats->alpha_data_size, stats->PSNR[4]);
|
stats->alpha_data_size, stats->PSNR[4]);
|
||||||
}
|
}
|
||||||
fprintf(stderr, " Residuals bytes "
|
fprintf(stderr,
|
||||||
|
" Residuals bytes "
|
||||||
"|segment 1|segment 2|segment 3"
|
"|segment 1|segment 2|segment 3"
|
||||||
"|segment 4| total\n");
|
"|segment 4| total\n");
|
||||||
if (full_details) {
|
if (full_details) {
|
||||||
@@ -346,7 +346,7 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
|||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -411,9 +411,9 @@ static int WriteMetadataChunk(FILE* const out, const char fourcc[4],
|
|||||||
|
|
||||||
// Sets 'flag' in 'vp8x_flags' and updates 'metadata_size' with the size of the
|
// Sets 'flag' in 'vp8x_flags' and updates 'metadata_size' with the size of the
|
||||||
// chunk if there is metadata and 'keep' is true.
|
// chunk if there is metadata and 'keep' is true.
|
||||||
static int UpdateFlagsAndSize(const MetadataPayload* const payload,
|
static int UpdateFlagsAndSize(const MetadataPayload* const payload, int keep,
|
||||||
int keep, int flag,
|
int flag, uint32_t* vp8x_flags,
|
||||||
uint32_t* vp8x_flags, uint64_t* metadata_size) {
|
uint64_t* metadata_size) {
|
||||||
if (keep && payload->bytes != NULL && payload->size > 0) {
|
if (keep && payload->bytes != NULL && payload->size > 0) {
|
||||||
*vp8x_flags |= flag;
|
*vp8x_flags |= flag;
|
||||||
*metadata_size += kChunkHeaderSize + payload->size + (payload->size & 1);
|
*metadata_size += kChunkHeaderSize + payload->size + (payload->size & 1);
|
||||||
@@ -442,14 +442,14 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
const size_t kMinSize = kRiffHeaderSize + kChunkHeaderSize;
|
const size_t kMinSize = kRiffHeaderSize + kChunkHeaderSize;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
uint64_t metadata_size = 0;
|
uint64_t metadata_size = 0;
|
||||||
const int write_exif = UpdateFlagsAndSize(&metadata->exif,
|
const int write_exif =
|
||||||
!!(keep_metadata & METADATA_EXIF),
|
UpdateFlagsAndSize(&metadata->exif, !!(keep_metadata & METADATA_EXIF),
|
||||||
kEXIFFlag, &flags, &metadata_size);
|
kEXIFFlag, &flags, &metadata_size);
|
||||||
const int write_iccp = UpdateFlagsAndSize(&metadata->iccp,
|
const int write_iccp =
|
||||||
!!(keep_metadata & METADATA_ICC),
|
UpdateFlagsAndSize(&metadata->iccp, !!(keep_metadata & METADATA_ICC),
|
||||||
kICCPFlag, &flags, &metadata_size);
|
kICCPFlag, &flags, &metadata_size);
|
||||||
const int write_xmp = UpdateFlagsAndSize(&metadata->xmp,
|
const int write_xmp =
|
||||||
!!(keep_metadata & METADATA_XMP),
|
UpdateFlagsAndSize(&metadata->xmp, !!(keep_metadata & METADATA_XMP),
|
||||||
kXMPFlag, &flags, &metadata_size);
|
kXMPFlag, &flags, &metadata_size);
|
||||||
uint8_t* webp = memory_writer->mem;
|
uint8_t* webp = memory_writer->mem;
|
||||||
size_t webp_size = memory_writer->size;
|
size_t webp_size = memory_writer->size;
|
||||||
@@ -458,7 +458,8 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
|
|
||||||
if (webp_size < kMinSize) return 0;
|
if (webp_size < kMinSize) return 0;
|
||||||
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
||||||
fprintf(stderr, "Error! Addition of metadata would exceed "
|
fprintf(stderr,
|
||||||
|
"Error! Addition of metadata would exceed "
|
||||||
"container size limit.\n");
|
"container size limit.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -466,9 +467,9 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
if (metadata_size > 0) {
|
if (metadata_size > 0) {
|
||||||
const int kVP8XChunkSize = 18;
|
const int kVP8XChunkSize = 18;
|
||||||
const int has_vp8x = !memcmp(webp + kRiffHeaderSize, "VP8X", kTagSize);
|
const int has_vp8x = !memcmp(webp + kRiffHeaderSize, "VP8X", kTagSize);
|
||||||
const uint32_t riff_size = (uint32_t)(webp_size - kChunkHeaderSize +
|
const uint32_t riff_size =
|
||||||
(has_vp8x ? 0 : kVP8XChunkSize) +
|
(uint32_t)(webp_size - kChunkHeaderSize +
|
||||||
metadata_size);
|
(has_vp8x ? 0 : kVP8XChunkSize) + metadata_size);
|
||||||
// RIFF
|
// RIFF
|
||||||
int ok = (fwrite(webp, kTagSize, 1, out) == 1);
|
int ok = (fwrite(webp, kTagSize, 1, out) == 1);
|
||||||
// RIFF size (file header size is not recorded)
|
// RIFF size (file header size is not recorded)
|
||||||
@@ -527,8 +528,7 @@ enum {
|
|||||||
RESIZE_MODE_DEFAULT = RESIZE_MODE_ALWAYS
|
RESIZE_MODE_DEFAULT = RESIZE_MODE_ALWAYS
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ApplyResizeMode(const int resize_mode,
|
static void ApplyResizeMode(const int resize_mode, const WebPPicture* const pic,
|
||||||
const WebPPicture* const pic,
|
|
||||||
int* const resize_w, int* const resize_h) {
|
int* const resize_w, int* const resize_h) {
|
||||||
const int src_w = pic->width;
|
const int src_w = pic->width;
|
||||||
const int src_h = pic->height;
|
const int src_h = pic->height;
|
||||||
@@ -536,8 +536,7 @@ static void ApplyResizeMode(const int resize_mode,
|
|||||||
const int dst_h = *resize_h;
|
const int dst_h = *resize_h;
|
||||||
|
|
||||||
if (resize_mode == RESIZE_MODE_DOWN_ONLY) {
|
if (resize_mode == RESIZE_MODE_DOWN_ONLY) {
|
||||||
if ((dst_w == 0 && src_h <= dst_h) ||
|
if ((dst_w == 0 && src_h <= dst_h) || (dst_h == 0 && src_w <= dst_w) ||
|
||||||
(dst_h == 0 && src_w <= dst_w) ||
|
|
||||||
(src_w <= dst_w && src_h <= dst_h)) {
|
(src_w <= dst_w && src_h <= dst_h)) {
|
||||||
*resize_w = *resize_h = 0;
|
*resize_w = *resize_h = 0;
|
||||||
}
|
}
|
||||||
@@ -551,8 +550,7 @@ static void ApplyResizeMode(const int resize_mode,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static int ProgressReport(int percent, const WebPPicture* const picture) {
|
static int ProgressReport(int percent, const WebPPicture* const picture) {
|
||||||
fprintf(stderr, "[%s]: %3d %% \r",
|
fprintf(stderr, "[%s]: %3d %% \r", (char*)picture->user_data, percent);
|
||||||
(char*)picture->user_data, percent);
|
|
||||||
return 1; // all ok
|
return 1; // all ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,7 +567,8 @@ static void HelpShort(void) {
|
|||||||
static void HelpLong(void) {
|
static void HelpLong(void) {
|
||||||
printf("Usage:\n");
|
printf("Usage:\n");
|
||||||
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
|
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
|
||||||
printf("If input size (-s) for an image is not specified, it is\n"
|
printf(
|
||||||
|
"If input size (-s) for an image is not specified, it is\n"
|
||||||
"assumed to be a PNG, JPEG, TIFF or WebP file.\n");
|
"assumed to be a PNG, JPEG, TIFF or WebP file.\n");
|
||||||
printf("Note: Animated PNG and WebP files are not supported.\n");
|
printf("Note: Animated PNG and WebP files are not supported.\n");
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
@@ -578,45 +577,58 @@ static void HelpLong(void) {
|
|||||||
printf("\nOptions:\n");
|
printf("\nOptions:\n");
|
||||||
printf(" -h / -help ............. short help\n");
|
printf(" -h / -help ............. short help\n");
|
||||||
printf(" -H / -longhelp ......... long help\n");
|
printf(" -H / -longhelp ......... long help\n");
|
||||||
printf(" -q <float> ............. quality factor (0:small..100:big), "
|
printf(
|
||||||
|
" -q <float> ............. quality factor (0:small..100:big), "
|
||||||
"default=75\n");
|
"default=75\n");
|
||||||
printf(" -alpha_q <int> ......... transparency-compression quality (0..100),"
|
printf(
|
||||||
|
" -alpha_q <int> ......... transparency-compression quality (0..100),"
|
||||||
"\n default=100\n");
|
"\n default=100\n");
|
||||||
printf(" -preset <string> ....... preset setting, one of:\n");
|
printf(" -preset <string> ....... preset setting, one of:\n");
|
||||||
printf(" default, photo, picture,\n");
|
printf(" default, photo, picture,\n");
|
||||||
printf(" drawing, icon, text\n");
|
printf(" drawing, icon, text\n");
|
||||||
printf(" -preset must come first, as it overwrites other parameters\n");
|
printf(" -preset must come first, as it overwrites other parameters\n");
|
||||||
printf(" -z <int> ............... activates lossless preset with given\n"
|
printf(
|
||||||
|
" -z <int> ............... activates lossless preset with given\n"
|
||||||
" level in [0:fast, ..., 9:slowest]\n");
|
" level in [0:fast, ..., 9:slowest]\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -m <int> ............... compression method (0=fast, 6=slowest), "
|
printf(
|
||||||
|
" -m <int> ............... compression method (0=fast, 6=slowest), "
|
||||||
"default=4\n");
|
"default=4\n");
|
||||||
printf(" -segments <int> ........ number of segments to use (1..4), "
|
printf(
|
||||||
|
" -segments <int> ........ number of segments to use (1..4), "
|
||||||
"default=4\n");
|
"default=4\n");
|
||||||
printf(" -size <int> ............ target size (in bytes)\n");
|
printf(" -size <int> ............ target size (in bytes)\n");
|
||||||
printf(" -psnr <float> .......... target PSNR (in dB. typically: 42)\n");
|
printf(" -psnr <float> .......... target PSNR (in dB. typically: 42)\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -s <int> <int> ......... input size (width x height) for YUV\n");
|
printf(" -s <int> <int> ......... input size (width x height) for YUV\n");
|
||||||
printf(" -sns <int> ............. spatial noise shaping (0:off, 100:max), "
|
printf(
|
||||||
|
" -sns <int> ............. spatial noise shaping (0:off, 100:max), "
|
||||||
"default=50\n");
|
"default=50\n");
|
||||||
printf(" -f <int> ............... filter strength (0=off..100), "
|
printf(
|
||||||
|
" -f <int> ............... filter strength (0=off..100), "
|
||||||
"default=60\n");
|
"default=60\n");
|
||||||
printf(" -sharpness <int> ....... "
|
printf(
|
||||||
|
" -sharpness <int> ....... "
|
||||||
"filter sharpness (0:most .. 7:least sharp), default=0\n");
|
"filter sharpness (0:most .. 7:least sharp), default=0\n");
|
||||||
printf(" -strong ................ use strong filter instead "
|
printf(
|
||||||
|
" -strong ................ use strong filter instead "
|
||||||
"of simple (default)\n");
|
"of simple (default)\n");
|
||||||
printf(" -nostrong .............. use simple filter instead of strong\n");
|
printf(" -nostrong .............. use simple filter instead of strong\n");
|
||||||
printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
printf(
|
||||||
|
" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
||||||
"conversion\n");
|
"conversion\n");
|
||||||
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
||||||
printf(" "
|
printf(
|
||||||
|
" "
|
||||||
"the first partition (0=no degradation ... 100=full)\n");
|
"the first partition (0=no degradation ... 100=full)\n");
|
||||||
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
||||||
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
|
printf(
|
||||||
|
" -qrange <min> <max> .... specifies the permissible quality range\n"
|
||||||
" (default: 0 100)\n");
|
" (default: 0 100)\n");
|
||||||
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
|
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
|
||||||
printf(" -resize <w> <h> ........ resize picture (*after* any cropping)\n");
|
printf(" -resize <w> <h> ........ resize picture (*after* any cropping)\n");
|
||||||
printf(" -resize_mode <string> .. one of: up_only, down_only,"
|
printf(
|
||||||
|
" -resize_mode <string> .. one of: up_only, down_only,"
|
||||||
" always (default)\n");
|
" always (default)\n");
|
||||||
printf(" -mt .................... use multi-threading if available\n");
|
printf(" -mt .................... use multi-threading if available\n");
|
||||||
printf(" -low_memory ............ reduce memory usage (slower encoding)\n");
|
printf(" -low_memory ............ reduce memory usage (slower encoding)\n");
|
||||||
@@ -625,19 +637,23 @@ static void HelpLong(void) {
|
|||||||
printf(" -print_ssim ............ prints averaged SSIM distortion\n");
|
printf(" -print_ssim ............ prints averaged SSIM distortion\n");
|
||||||
printf(" -print_lsim ............ prints local-similarity distortion\n");
|
printf(" -print_lsim ............ prints local-similarity distortion\n");
|
||||||
printf(" -d <file.pgm> .......... dump the compressed output (PGM file)\n");
|
printf(" -d <file.pgm> .......... dump the compressed output (PGM file)\n");
|
||||||
printf(" -alpha_method <int> .... transparency-compression method (0..1), "
|
printf(
|
||||||
|
" -alpha_method <int> .... transparency-compression method (0..1), "
|
||||||
"default=1\n");
|
"default=1\n");
|
||||||
printf(" -alpha_filter <string> . predictive filtering for alpha plane,\n");
|
printf(" -alpha_filter <string> . predictive filtering for alpha plane,\n");
|
||||||
printf(" one of: none, fast (default) or best\n");
|
printf(" one of: none, fast (default) or best\n");
|
||||||
printf(" -exact ................. preserve RGB values in transparent area, "
|
printf(
|
||||||
|
" -exact ................. preserve RGB values in transparent area, "
|
||||||
"default=off\n");
|
"default=off\n");
|
||||||
printf(" -blend_alpha <hex> ..... blend colors against background color\n"
|
printf(
|
||||||
|
" -blend_alpha <hex> ..... blend colors against background color\n"
|
||||||
" expressed as RGB values written in\n"
|
" expressed as RGB values written in\n"
|
||||||
" hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n"
|
" hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n"
|
||||||
" green=0xe0 and blue=0xd0\n");
|
" green=0xe0 and blue=0xd0\n");
|
||||||
printf(" -noalpha ............... discard any transparency information\n");
|
printf(" -noalpha ............... discard any transparency information\n");
|
||||||
printf(" -lossless .............. encode image losslessly, default=off\n");
|
printf(" -lossless .............. encode image losslessly, default=off\n");
|
||||||
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n"
|
printf(
|
||||||
|
" -near_lossless <int> ... use near-lossless image preprocessing\n"
|
||||||
" (0..100=off), default=100\n");
|
" (0..100=off), default=100\n");
|
||||||
printf(" -hint <string> ......... specify image characteristics hint,\n");
|
printf(" -hint <string> ......... specify image characteristics hint,\n");
|
||||||
printf(" one of: photo, picture or graph\n");
|
printf(" one of: photo, picture or graph\n");
|
||||||
@@ -646,7 +662,8 @@ static void HelpLong(void) {
|
|||||||
printf(" -metadata <string> ..... comma separated list of metadata to\n");
|
printf(" -metadata <string> ..... comma separated list of metadata to\n");
|
||||||
printf(" ");
|
printf(" ");
|
||||||
printf("copy from the input to the output if present.\n");
|
printf("copy from the input to the output if present.\n");
|
||||||
printf(" "
|
printf(
|
||||||
|
" "
|
||||||
"Valid values: all, none (default), exif, icc, xmp\n");
|
"Valid values: all, none (default), exif, icc, xmp\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -656,7 +673,8 @@ static void HelpLong(void) {
|
|||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
printf(" -noasm ................. disable all assembly optimizations\n");
|
printf(" -noasm ................. disable all assembly optimizations\n");
|
||||||
#endif
|
#endif
|
||||||
printf(" -v ..................... verbose, e.g. print encoding/decoding "
|
printf(
|
||||||
|
" -v ..................... verbose, e.g. print encoding/decoding "
|
||||||
"times\n");
|
"times\n");
|
||||||
printf(" -progress .............. report encoding progress\n");
|
printf(" -progress .............. report encoding progress\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -687,15 +705,14 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
|
|||||||
"PARTITION_OVERFLOW: Partition is too big to fit 16M",
|
"PARTITION_OVERFLOW: Partition is too big to fit 16M",
|
||||||
"BAD_WRITE: Picture writer returned an I/O error",
|
"BAD_WRITE: Picture writer returned an I/O error",
|
||||||
"FILE_TOO_BIG: File would be too big to fit in 4G",
|
"FILE_TOO_BIG: File would be too big to fit in 4G",
|
||||||
"USER_ABORT: encoding abort requested by user"
|
"USER_ABORT: encoding abort requested by user"};
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
int return_value = EXIT_FAILURE;
|
int return_value = EXIT_FAILURE;
|
||||||
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL;
|
const char *in_file = NULL, *out_file = NULL, *dump_file = NULL;
|
||||||
FILE* out = NULL;
|
FILE* out = NULL;
|
||||||
int c;
|
int c;
|
||||||
int short_output = 0;
|
int short_output = 0;
|
||||||
@@ -725,8 +742,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
MetadataInit(&metadata);
|
MetadataInit(&metadata);
|
||||||
WebPMemoryWriterInit(&memory_writer);
|
WebPMemoryWriterInit(&memory_writer);
|
||||||
if (!WebPPictureInit(&picture) ||
|
if (!WebPPictureInit(&picture) || !WebPPictureInit(&original_picture) ||
|
||||||
!WebPPictureInit(&original_picture) ||
|
|
||||||
!WebPConfigInit(&config)) {
|
!WebPConfigInit(&config)) {
|
||||||
fprintf(stderr, "Error! Version mismatch!\n");
|
fprintf(stderr, "Error! Version mismatch!\n");
|
||||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||||
@@ -766,8 +782,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
|
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
|
||||||
picture.height > WEBP_MAX_DIMENSION || picture.height < 0) {
|
picture.height > WEBP_MAX_DIMENSION || picture.height < 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Specified dimension (%d x %d) is out of range.\n",
|
||||||
"Specified dimension (%d x %d) is out of range.\n",
|
|
||||||
picture.width, picture.height);
|
picture.width, picture.height);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
@@ -892,11 +907,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
const int version = WebPGetEncoderVersion();
|
const int version = WebPGetEncoderVersion();
|
||||||
const int sharpyuv_version = SharpYuvGetVersion();
|
const int sharpyuv_version = SharpYuvGetVersion();
|
||||||
printf("%d.%d.%d\n",
|
printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff,
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
version & 0xff);
|
||||||
printf("libsharpyuv: %d.%d.%d\n",
|
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff,
|
||||||
(sharpyuv_version >> 24) & 0xff, (sharpyuv_version >> 16) & 0xffff,
|
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
|
||||||
sharpyuv_version & 0xff);
|
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||||
} else if (!strcmp(argv[c], "-progress")) {
|
} else if (!strcmp(argv[c], "-progress")) {
|
||||||
show_progress = 1;
|
show_progress = 1;
|
||||||
@@ -930,11 +944,11 @@ int main(int argc, const char* argv[]) {
|
|||||||
const char* option;
|
const char* option;
|
||||||
int flag;
|
int flag;
|
||||||
} kTokens[] = {
|
} kTokens[] = {
|
||||||
{ "all", METADATA_ALL },
|
{"all", METADATA_ALL}, //
|
||||||
{ "none", 0 },
|
{"none", 0}, //
|
||||||
{ "exif", METADATA_EXIF },
|
{"exif", METADATA_EXIF}, //
|
||||||
{ "icc", METADATA_ICC },
|
{"icc", METADATA_ICC}, //
|
||||||
{ "xmp", METADATA_XMP },
|
{"xmp", METADATA_XMP}, //
|
||||||
};
|
};
|
||||||
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
||||||
const char* start = argv[++c];
|
const char* start = argv[++c];
|
||||||
@@ -966,7 +980,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
if (keep_metadata != 0 && keep_metadata != METADATA_ICC) {
|
if (keep_metadata != 0 && keep_metadata != METADATA_ICC) {
|
||||||
// TODO(jzern): remove when -metadata is supported on all platforms.
|
// TODO(jzern): remove when -metadata is supported on all platforms.
|
||||||
fprintf(stderr, "Warning: only ICC profile extraction is currently"
|
fprintf(stderr,
|
||||||
|
"Warning: only ICC profile extraction is currently"
|
||||||
" supported on this platform!\n");
|
" supported on this platform!\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1005,11 +1020,13 @@ int main(int argc, const char* argv[]) {
|
|||||||
// warning for such options.
|
// warning for such options.
|
||||||
if (!quiet && config.lossless == 1) {
|
if (!quiet && config.lossless == 1) {
|
||||||
if (config.target_size > 0 || config.target_PSNR > 0) {
|
if (config.target_size > 0 || config.target_PSNR > 0) {
|
||||||
fprintf(stderr, "Encoding for specified size or PSNR is not supported"
|
fprintf(stderr,
|
||||||
|
"Encoding for specified size or PSNR is not supported"
|
||||||
" for lossless encoding. Ignoring such option(s)!\n");
|
" for lossless encoding. Ignoring such option(s)!\n");
|
||||||
}
|
}
|
||||||
if (config.partition_limit > 0) {
|
if (config.partition_limit > 0) {
|
||||||
fprintf(stderr, "Partition limit option is not required for lossless"
|
fprintf(stderr,
|
||||||
|
"Partition limit option is not required for lossless"
|
||||||
" encoding. Ignoring this option!\n");
|
" encoding. Ignoring this option!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1027,8 +1044,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
// Read the input. We need to decide if we prefer ARGB or YUVA
|
// Read the input. We need to decide if we prefer ARGB or YUVA
|
||||||
// samples, depending on the expected compression mode (this saves
|
// samples, depending on the expected compression mode (this saves
|
||||||
// some conversion steps).
|
// some conversion steps).
|
||||||
picture.use_argb = (config.lossless || config.use_sharp_yuv ||
|
picture.use_argb =
|
||||||
config.preprocessing > 0 ||
|
(config.lossless || config.use_sharp_yuv || config.preprocessing > 0 ||
|
||||||
crop || (resize_w | resize_h) > 0);
|
crop || (resize_w | resize_h) > 0);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
StopwatchReset(&stop_watch);
|
StopwatchReset(&stop_watch);
|
||||||
@@ -1177,8 +1194,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
if (!WebPEncode(&config, &picture)) {
|
if (!WebPEncode(&config, &picture)) {
|
||||||
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
|
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
|
||||||
fprintf(stderr, "Error code: %d (%s)\n",
|
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
|
||||||
picture.error_code, kErrorMessages[picture.error_code]);
|
kErrorMessages[picture.error_code]);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
@@ -1221,7 +1238,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
// Write the YUV planes to a PGM file. Only available for lossy.
|
// Write the YUV planes to a PGM file. Only available for lossy.
|
||||||
if (dump_file) {
|
if (dump_file) {
|
||||||
if (picture.use_argb) {
|
if (picture.use_argb) {
|
||||||
fprintf(stderr, "Warning: can't dump file (-d option) "
|
fprintf(stderr,
|
||||||
|
"Warning: can't dump file (-d option) "
|
||||||
"in lossless mode.\n");
|
"in lossless mode.\n");
|
||||||
} else if (!DumpPicture(&picture, dump_file)) {
|
} else if (!DumpPicture(&picture, dump_file)) {
|
||||||
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n",
|
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n",
|
||||||
@@ -1268,17 +1286,17 @@ int main(int argc, const char* argv[]) {
|
|||||||
PrintMapInfo(&picture);
|
PrintMapInfo(&picture);
|
||||||
}
|
}
|
||||||
if (print_distortion >= 0) { // print distortion
|
if (print_distortion >= 0) { // print distortion
|
||||||
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
static const char* distortion_names[] = {"PSNR", "SSIM", "LSIM"};
|
||||||
float values[5];
|
float values[5];
|
||||||
if (!WebPPictureDistortion(&picture, &original_picture,
|
if (!WebPPictureDistortion(&picture, &original_picture, print_distortion,
|
||||||
print_distortion, values)) {
|
values)) {
|
||||||
fprintf(stderr, "Error while computing the distortion.\n");
|
fprintf(stderr, "Error while computing the distortion.\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
if (!short_output) {
|
if (!short_output) {
|
||||||
fprintf(stderr, "%s: ", distortion_names[print_distortion]);
|
fprintf(stderr, "%s: ", distortion_names[print_distortion]);
|
||||||
fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n",
|
fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n", values[0],
|
||||||
values[0], values[1], values[2], values[3], values[4]);
|
values[1], values[2], values[3], values[4]);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]);
|
fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]);
|
||||||
}
|
}
|
||||||
@@ -1289,7 +1307,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
return_value = EXIT_SUCCESS;
|
return_value = EXIT_SUCCESS;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPMemoryWriterClear(&memory_writer);
|
WebPMemoryWriterClear(&memory_writer);
|
||||||
WebPFree(picture.extra_info);
|
WebPFree(picture.extra_info);
|
||||||
MetadataFree(&metadata);
|
MetadataFree(&metadata);
|
||||||
|
|||||||
125
examples/dwebp.c
125
examples/dwebp.c
@@ -42,7 +42,6 @@ extern void* VP8GetCPUInfo; // opaque forward declaration.
|
|||||||
#endif
|
#endif
|
||||||
#endif // WEBP_DLL
|
#endif // WEBP_DLL
|
||||||
|
|
||||||
|
|
||||||
static int SaveOutput(const WebPDecBuffer* const buffer,
|
static int SaveOutput(const WebPDecBuffer* const buffer,
|
||||||
WebPOutputFileFormat format, const char* const out_file) {
|
WebPOutputFileFormat format, const char* const out_file) {
|
||||||
const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-");
|
const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-");
|
||||||
@@ -77,7 +76,8 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Help(void) {
|
static void Help(void) {
|
||||||
printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
|
printf(
|
||||||
|
"Usage: dwebp in_file [options] [-o out_file]\n\n"
|
||||||
"Decodes the WebP image file to PNG format [Default].\n"
|
"Decodes the WebP image file to PNG format [Default].\n"
|
||||||
"Note: Animated WebP files are not supported.\n\n"
|
"Note: Animated WebP files are not supported.\n\n"
|
||||||
"Use following options to convert into alternate image formats:\n"
|
"Use following options to convert into alternate image formats:\n"
|
||||||
@@ -111,9 +111,7 @@ static void Help(void) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const kFormatType[] = {
|
static const char* const kFormatType[] = {"unspecified", "lossy", "lossless"};
|
||||||
"unspecified", "lossy", "lossless"
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
||||||
WebPOutputFileFormat format,
|
WebPOutputFileFormat format,
|
||||||
@@ -130,9 +128,9 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
|||||||
h = config->options.crop_height;
|
h = config->options.crop_height;
|
||||||
}
|
}
|
||||||
if (format >= RGB && format <= rgbA_4444) {
|
if (format >= RGB && format <= rgbA_4444) {
|
||||||
const int bpp = (format == RGB || format == BGR) ? 3
|
const int bpp =
|
||||||
: (format == RGBA_4444 || format == rgbA_4444 ||
|
(format == RGB || format == BGR) ? 3
|
||||||
format == RGB_565) ? 2
|
: (format == RGBA_4444 || format == rgbA_4444 || format == RGB_565) ? 2
|
||||||
: 4;
|
: 4;
|
||||||
uint32_t stride = bpp * w + 7; // <- just for exercising
|
uint32_t stride = bpp * w + 7; // <- just for exercising
|
||||||
external_buffer = (uint8_t*)WebPMalloc(stride * h);
|
external_buffer = (uint8_t*)WebPMalloc(stride * h);
|
||||||
@@ -145,8 +143,8 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
|||||||
uint8_t* tmp;
|
uint8_t* tmp;
|
||||||
uint32_t stride = w + 3;
|
uint32_t stride = w + 3;
|
||||||
uint32_t uv_stride = (w + 1) / 2 + 13;
|
uint32_t uv_stride = (w + 1) / 2 + 13;
|
||||||
uint32_t total_size = stride * h * (has_alpha ? 2 : 1)
|
uint32_t total_size =
|
||||||
+ 2 * uv_stride * (h + 1) / 2;
|
stride * h * (has_alpha ? 2 : 1) + 2 * uv_stride * (h + 1) / 2;
|
||||||
assert(format >= YUV && format <= YUVA);
|
assert(format >= YUV && format <= YUVA);
|
||||||
external_buffer = (uint8_t*)WebPMalloc(total_size);
|
external_buffer = (uint8_t*)WebPMalloc(total_size);
|
||||||
if (external_buffer == NULL) return NULL;
|
if (external_buffer == NULL) return NULL;
|
||||||
@@ -228,8 +226,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
quiet = 1;
|
quiet = 1;
|
||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
const int version = WebPGetDecoderVersion();
|
const int version = WebPGetDecoderVersion();
|
||||||
printf("%d.%d.%d\n",
|
printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff,
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
version & 0xff);
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||||
} else if (!strcmp(argv[c], "-pgm")) {
|
} else if (!strcmp(argv[c], "-pgm")) {
|
||||||
format = PGM;
|
format = PGM;
|
||||||
@@ -237,19 +235,32 @@ int main(int argc, const char* argv[]) {
|
|||||||
format = RAW_YUV;
|
format = RAW_YUV;
|
||||||
} else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) {
|
||||||
const char* const fmt = argv[++c];
|
const char* const fmt = argv[++c];
|
||||||
if (!strcmp(fmt, "RGB")) format = RGB;
|
if (!strcmp(fmt, "RGB"))
|
||||||
else if (!strcmp(fmt, "RGBA")) format = RGBA;
|
format = RGB;
|
||||||
else if (!strcmp(fmt, "BGR")) format = BGR;
|
else if (!strcmp(fmt, "RGBA"))
|
||||||
else if (!strcmp(fmt, "BGRA")) format = BGRA;
|
format = RGBA;
|
||||||
else if (!strcmp(fmt, "ARGB")) format = ARGB;
|
else if (!strcmp(fmt, "BGR"))
|
||||||
else if (!strcmp(fmt, "RGBA_4444")) format = RGBA_4444;
|
format = BGR;
|
||||||
else if (!strcmp(fmt, "RGB_565")) format = RGB_565;
|
else if (!strcmp(fmt, "BGRA"))
|
||||||
else if (!strcmp(fmt, "rgbA")) format = rgbA;
|
format = BGRA;
|
||||||
else if (!strcmp(fmt, "bgrA")) format = bgrA;
|
else if (!strcmp(fmt, "ARGB"))
|
||||||
else if (!strcmp(fmt, "Argb")) format = Argb;
|
format = ARGB;
|
||||||
else if (!strcmp(fmt, "rgbA_4444")) format = rgbA_4444;
|
else if (!strcmp(fmt, "RGBA_4444"))
|
||||||
else if (!strcmp(fmt, "YUV")) format = YUV;
|
format = RGBA_4444;
|
||||||
else if (!strcmp(fmt, "YUVA")) format = YUVA;
|
else if (!strcmp(fmt, "RGB_565"))
|
||||||
|
format = RGB_565;
|
||||||
|
else if (!strcmp(fmt, "rgbA"))
|
||||||
|
format = rgbA;
|
||||||
|
else if (!strcmp(fmt, "bgrA"))
|
||||||
|
format = bgrA;
|
||||||
|
else if (!strcmp(fmt, "Argb"))
|
||||||
|
format = Argb;
|
||||||
|
else if (!strcmp(fmt, "rgbA_4444"))
|
||||||
|
format = rgbA_4444;
|
||||||
|
else if (!strcmp(fmt, "YUV"))
|
||||||
|
format = YUV;
|
||||||
|
else if (!strcmp(fmt, "YUVA"))
|
||||||
|
format = YUVA;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Can't parse pixel_format %s\n", fmt);
|
fprintf(stderr, "Can't parse pixel_format %s\n", fmt);
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
@@ -350,25 +361,52 @@ int main(int argc, const char* argv[]) {
|
|||||||
output_buffer->colorspace = MODE_YUVA;
|
output_buffer->colorspace = MODE_YUVA;
|
||||||
break;
|
break;
|
||||||
// forced modes:
|
// forced modes:
|
||||||
case RGB: output_buffer->colorspace = MODE_RGB; break;
|
case RGB:
|
||||||
case RGBA: output_buffer->colorspace = MODE_RGBA; break;
|
output_buffer->colorspace = MODE_RGB;
|
||||||
case BGR: output_buffer->colorspace = MODE_BGR; break;
|
break;
|
||||||
case BGRA: output_buffer->colorspace = MODE_BGRA; break;
|
case RGBA:
|
||||||
case ARGB: output_buffer->colorspace = MODE_ARGB; break;
|
output_buffer->colorspace = MODE_RGBA;
|
||||||
case RGBA_4444: output_buffer->colorspace = MODE_RGBA_4444; break;
|
break;
|
||||||
case RGB_565: output_buffer->colorspace = MODE_RGB_565; break;
|
case BGR:
|
||||||
case rgbA: output_buffer->colorspace = MODE_rgbA; break;
|
output_buffer->colorspace = MODE_BGR;
|
||||||
case bgrA: output_buffer->colorspace = MODE_bgrA; break;
|
break;
|
||||||
case Argb: output_buffer->colorspace = MODE_Argb; break;
|
case BGRA:
|
||||||
case rgbA_4444: output_buffer->colorspace = MODE_rgbA_4444; break;
|
output_buffer->colorspace = MODE_BGRA;
|
||||||
case YUV: output_buffer->colorspace = MODE_YUV; break;
|
break;
|
||||||
case YUVA: output_buffer->colorspace = MODE_YUVA; break;
|
case ARGB:
|
||||||
default: goto Exit;
|
output_buffer->colorspace = MODE_ARGB;
|
||||||
|
break;
|
||||||
|
case RGBA_4444:
|
||||||
|
output_buffer->colorspace = MODE_RGBA_4444;
|
||||||
|
break;
|
||||||
|
case RGB_565:
|
||||||
|
output_buffer->colorspace = MODE_RGB_565;
|
||||||
|
break;
|
||||||
|
case rgbA:
|
||||||
|
output_buffer->colorspace = MODE_rgbA;
|
||||||
|
break;
|
||||||
|
case bgrA:
|
||||||
|
output_buffer->colorspace = MODE_bgrA;
|
||||||
|
break;
|
||||||
|
case Argb:
|
||||||
|
output_buffer->colorspace = MODE_Argb;
|
||||||
|
break;
|
||||||
|
case rgbA_4444:
|
||||||
|
output_buffer->colorspace = MODE_rgbA_4444;
|
||||||
|
break;
|
||||||
|
case YUV:
|
||||||
|
output_buffer->colorspace = MODE_YUV;
|
||||||
|
break;
|
||||||
|
case YUVA:
|
||||||
|
output_buffer->colorspace = MODE_YUVA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_external_memory > 0 && format >= RGB) {
|
if (use_external_memory > 0 && format >= RGB) {
|
||||||
external_buffer = AllocateExternalBuffer(&config, format,
|
external_buffer =
|
||||||
use_external_memory);
|
AllocateExternalBuffer(&config, format, use_external_memory);
|
||||||
if (external_buffer == NULL) goto Exit;
|
if (external_buffer == NULL) goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,11 +448,12 @@ int main(int argc, const char* argv[]) {
|
|||||||
output_buffer->width, output_buffer->height,
|
output_buffer->width, output_buffer->height,
|
||||||
bitstream->has_alpha ? " (with alpha)" : "",
|
bitstream->has_alpha ? " (with alpha)" : "",
|
||||||
kFormatType[bitstream->format]);
|
kFormatType[bitstream->format]);
|
||||||
fprintf(stderr, "Nothing written; "
|
fprintf(stderr,
|
||||||
|
"Nothing written; "
|
||||||
"use -o flag to save the result as e.g. PNG.\n");
|
"use -o flag to save the result as e.g. PNG.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Exit:
|
Exit:
|
||||||
WebPFreeDecBuffer(output_buffer);
|
WebPFreeDecBuffer(output_buffer);
|
||||||
WebPFree((void*)external_buffer);
|
WebPFree((void*)external_buffer);
|
||||||
WebPFree((void*)data);
|
WebPFree((void*)data);
|
||||||
|
|||||||
@@ -110,8 +110,7 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
argc = 0;
|
argc = 0;
|
||||||
for (cur = strtok((char*)args->argv_data.bytes, sep);
|
for (cur = strtok((char*)args->argv_data.bytes, sep); cur != NULL;
|
||||||
cur != NULL;
|
|
||||||
cur = strtok(NULL, sep)) {
|
cur = strtok(NULL, sep)) {
|
||||||
if (argc == MAX_ARGC) {
|
if (argc == MAX_ARGC) {
|
||||||
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
|
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
|
|
||||||
#include "webp/types.h"
|
|
||||||
#include "webp/mux_types.h"
|
#include "webp/mux_types.h"
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -28,14 +28,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gif_lib.h>
|
#include <gif_lib.h>
|
||||||
#include "sharpyuv/sharpyuv.h"
|
|
||||||
#include "webp/encode.h"
|
|
||||||
#include "webp/mux.h"
|
|
||||||
#include "../examples/example_util.h"
|
#include "../examples/example_util.h"
|
||||||
#include "../imageio/imageio_util.h"
|
#include "../imageio/imageio_util.h"
|
||||||
#include "./gifdec.h"
|
#include "./gifdec.h"
|
||||||
#include "./unicode.h"
|
#include "./unicode.h"
|
||||||
#include "./unicode_gif.h"
|
#include "./unicode_gif.h"
|
||||||
|
#include "sharpyuv/sharpyuv.h"
|
||||||
|
#include "webp/encode.h"
|
||||||
|
#include "webp/mux.h"
|
||||||
|
|
||||||
#if !defined(STDIN_FILENO)
|
#if !defined(STDIN_FILENO)
|
||||||
#define STDIN_FILENO 0
|
#define STDIN_FILENO 0
|
||||||
@@ -47,8 +48,7 @@ static int transparent_index = GIF_INDEX_INVALID; // Opaque by default.
|
|||||||
|
|
||||||
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
||||||
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
||||||
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"
|
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"};
|
||||||
};
|
|
||||||
|
|
||||||
static const char* ErrorString(WebPMuxError err) {
|
static const char* ErrorString(WebPMuxError err) {
|
||||||
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
||||||
@@ -69,17 +69,22 @@ static void Help(void) {
|
|||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -h / -help ............. this help\n");
|
printf(" -h / -help ............. this help\n");
|
||||||
printf(" -lossy ................. encode image using lossy compression\n");
|
printf(" -lossy ................. encode image using lossy compression\n");
|
||||||
printf(" -mixed ................. for each frame in the image, pick lossy\n"
|
printf(
|
||||||
|
" -mixed ................. for each frame in the image, pick lossy\n"
|
||||||
" or lossless compression heuristically\n");
|
" or lossless compression heuristically\n");
|
||||||
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n"
|
printf(
|
||||||
|
" -near_lossless <int> ... use near-lossless image preprocessing\n"
|
||||||
" (0..100=off), default=100\n");
|
" (0..100=off), default=100\n");
|
||||||
printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
printf(
|
||||||
|
" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
||||||
"conversion\n"
|
"conversion\n"
|
||||||
" (lossy only)\n");
|
" (lossy only)\n");
|
||||||
printf(" -q <float> ............. quality factor (0:small..100:big)\n");
|
printf(" -q <float> ............. quality factor (0:small..100:big)\n");
|
||||||
printf(" -m <int> ............... compression method (0=fast, 6=slowest), "
|
printf(
|
||||||
|
" -m <int> ............... compression method (0=fast, 6=slowest), "
|
||||||
"default=4\n");
|
"default=4\n");
|
||||||
printf(" -min_size .............. minimize output size (default:off)\n"
|
printf(
|
||||||
|
" -min_size .............. minimize output size (default:off)\n"
|
||||||
" lossless compression by default; can be\n"
|
" lossless compression by default; can be\n"
|
||||||
" combined with -q, -m, -lossy or -mixed\n"
|
" combined with -q, -m, -lossy or -mixed\n"
|
||||||
" options\n");
|
" options\n");
|
||||||
@@ -109,7 +114,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
int gif_error = GIF_ERROR;
|
int gif_error = GIF_ERROR;
|
||||||
WebPMuxError err = WEBP_MUX_OK;
|
WebPMuxError err = WEBP_MUX_OK;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
const W_CHAR* in_file = NULL, *out_file = NULL;
|
const W_CHAR *in_file = NULL, *out_file = NULL;
|
||||||
GifFileType* gif = NULL;
|
GifFileType* gif = NULL;
|
||||||
int frame_duration = 0;
|
int frame_duration = 0;
|
||||||
int frame_timestamp = 0;
|
int frame_timestamp = 0;
|
||||||
@@ -198,10 +203,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
const char* option;
|
const char* option;
|
||||||
int flag;
|
int flag;
|
||||||
} kTokens[] = {
|
} kTokens[] = {
|
||||||
{ "all", METADATA_ALL },
|
{"all", METADATA_ALL},
|
||||||
{ "none", 0 },
|
{"none", 0},
|
||||||
{ "icc", METADATA_ICC },
|
{"icc", METADATA_ICC},
|
||||||
{ "xmp", METADATA_XMP },
|
{"xmp", METADATA_XMP},
|
||||||
};
|
};
|
||||||
const size_t kNumTokens = sizeof(kTokens) / sizeof(*kTokens);
|
const size_t kNumTokens = sizeof(kTokens) / sizeof(*kTokens);
|
||||||
const char* start = argv[++c];
|
const char* start = argv[++c];
|
||||||
@@ -319,8 +324,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf("Fixed canvas screen dimension to: %d x %d\n",
|
printf("Fixed canvas screen dimension to: %d x %d\n", gif->SWidth,
|
||||||
gif->SWidth, gif->SHeight);
|
gif->SHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Allocate current buffer.
|
// Allocate current buffer.
|
||||||
@@ -555,8 +560,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
err = WebPMuxAssemble(mux, &webp_data);
|
err = WebPMuxAssemble(mux, &webp_data);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
fprintf(stderr, "ERROR (%s): Could not assemble when re-muxing to add "
|
fprintf(stderr,
|
||||||
"loop count/metadata.\n", ErrorString(err));
|
"ERROR (%s): Could not assemble when re-muxing to add "
|
||||||
|
"loop count/metadata.\n",
|
||||||
|
ErrorString(err));
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -569,8 +576,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
if (!WSTRCMP(out_file, "-")) {
|
if (!WSTRCMP(out_file, "-")) {
|
||||||
fprintf(stderr, "Saved %d bytes to STDIO\n",
|
fprintf(stderr, "Saved %d bytes to STDIO\n", (int)webp_data.size);
|
||||||
(int)webp_data.size);
|
|
||||||
} else {
|
} else {
|
||||||
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
|
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
|
||||||
(int)webp_data.size, out_file);
|
(int)webp_data.size, out_file);
|
||||||
@@ -578,8 +584,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
fprintf(stderr, "Nothing written; use -o flag to save the result "
|
fprintf(stderr,
|
||||||
"(%d bytes).\n", (int)webp_data.size);
|
"Nothing written; use -o flag to save the result "
|
||||||
|
"(%d bytes).\n",
|
||||||
|
(int)webp_data.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,7 +595,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
ok = 1;
|
ok = 1;
|
||||||
gif_error = GIF_OK;
|
gif_error = GIF_OK;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
WebPDataClear(&icc_data);
|
WebPDataClear(&icc_data);
|
||||||
WebPDataClear(&xmp_data);
|
WebPDataClear(&xmp_data);
|
||||||
WebPMuxDelete(mux);
|
WebPMuxDelete(mux);
|
||||||
@@ -601,7 +609,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
GIFDisplayError(gif, gif_error);
|
GIFDisplayError(gif, gif_error);
|
||||||
}
|
}
|
||||||
if (gif != NULL) {
|
if (gif != NULL) {
|
||||||
#if LOCAL_GIF_PREREQ(5,1)
|
#if LOCAL_GIF_PREREQ(5, 1)
|
||||||
DGifCloseFile(gif, &gif_error);
|
DGifCloseFile(gif, &gif_error);
|
||||||
#else
|
#else
|
||||||
DGifCloseFile(gif);
|
DGifCloseFile(gif);
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "webp/types.h"
|
|
||||||
#include "webp/mux_types.h"
|
#include "webp/mux_types.h"
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
#define GIF_TRANSPARENT_COLOR 0x00000000u
|
#define GIF_TRANSPARENT_COLOR 0x00000000u
|
||||||
#define GIF_WHITE_COLOR 0xffffffffu
|
#define GIF_WHITE_COLOR 0xffffffffu
|
||||||
@@ -32,9 +32,8 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
extern void WebPCopyPlane(const uint8_t* src, int src_stride,
|
extern void WebPCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst,
|
||||||
uint8_t* dst, int dst_stride,
|
int dst_stride, int width, int height);
|
||||||
int width, int height);
|
|
||||||
extern void WebPCopyPixels(const WebPPicture* const src,
|
extern void WebPCopyPixels(const WebPPicture* const src,
|
||||||
WebPPicture* const dst);
|
WebPPicture* const dst);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -47,18 +46,16 @@ void GIFGetBackgroundColor(const ColorMapObject* const color_map,
|
|||||||
if (transparent_index != GIF_INDEX_INVALID &&
|
if (transparent_index != GIF_INDEX_INVALID &&
|
||||||
bgcolor_index == transparent_index) {
|
bgcolor_index == transparent_index) {
|
||||||
*bgcolor = GIF_TRANSPARENT_COLOR; // Special case.
|
*bgcolor = GIF_TRANSPARENT_COLOR; // Special case.
|
||||||
} else if (color_map == NULL || color_map->Colors == NULL
|
} else if (color_map == NULL || color_map->Colors == NULL ||
|
||||||
|| bgcolor_index >= color_map->ColorCount) {
|
bgcolor_index >= color_map->ColorCount) {
|
||||||
*bgcolor = GIF_WHITE_COLOR;
|
*bgcolor = GIF_WHITE_COLOR;
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"GIF decode warning: invalid background color index. Assuming "
|
"GIF decode warning: invalid background color index. Assuming "
|
||||||
"white background.\n");
|
"white background.\n");
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[bgcolor_index];
|
const GifColorType color = color_map->Colors[bgcolor_index];
|
||||||
*bgcolor = (0xffu << 24)
|
*bgcolor = (0xffu << 24) | (color.Red << 16) | (color.Green << 8) |
|
||||||
| (color.Red << 16)
|
(color.Blue << 0);
|
||||||
| (color.Green << 8)
|
|
||||||
| (color.Blue << 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,9 +114,8 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
const GifImageDesc* const image_desc = &gif->Image;
|
const GifImageDesc* const image_desc = &gif->Image;
|
||||||
uint32_t* dst = NULL;
|
uint32_t* dst = NULL;
|
||||||
uint8_t* tmp = NULL;
|
uint8_t* tmp = NULL;
|
||||||
const GIFFrameRect rect = {
|
const GIFFrameRect rect = {image_desc->Left, image_desc->Top,
|
||||||
image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
|
image_desc->Width, image_desc->Height};
|
||||||
};
|
|
||||||
const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
|
const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
*gif_rect = rect;
|
*gif_rect = rect;
|
||||||
@@ -130,8 +126,8 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use a view for the sub-picture:
|
// Use a view for the sub-picture:
|
||||||
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
|
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset, rect.width,
|
||||||
rect.width, rect.height, &sub_image)) {
|
rect.height, &sub_image)) {
|
||||||
fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
|
fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
|
||||||
rect.width, rect.height, rect.x_offset, rect.y_offset);
|
rect.width, rect.height, rect.x_offset, rect.y_offset);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -143,8 +139,8 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
|
|
||||||
if (image_desc->Interlace) { // Interlaced image.
|
if (image_desc->Interlace) { // Interlaced image.
|
||||||
// We need 4 passes, with the following offsets and jumps.
|
// We need 4 passes, with the following offsets and jumps.
|
||||||
const int interlace_offsets[] = { 0, 4, 2, 1 };
|
const int interlace_offsets[] = {0, 4, 2, 1};
|
||||||
const int interlace_jumps[] = { 8, 8, 4, 2 };
|
const int interlace_jumps[] = {8, 8, 4, 2};
|
||||||
int pass;
|
int pass;
|
||||||
for (pass = 0; pass < 4; ++pass) {
|
for (pass = 0; pass < 4; ++pass) {
|
||||||
const size_t stride = (size_t)sub_image.argb_stride;
|
const size_t stride = (size_t)sub_image.argb_stride;
|
||||||
@@ -166,7 +162,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
if (!ok) picture->error_code = sub_image.error_code;
|
if (!ok) picture->error_code = sub_image.error_code;
|
||||||
WebPPictureFree(&sub_image);
|
WebPPictureFree(&sub_image);
|
||||||
WebPFree(tmp);
|
WebPFree(tmp);
|
||||||
@@ -220,8 +216,7 @@ int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
|
|||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy((void*)(tmp + metadata->size),
|
memcpy((void*)(tmp + metadata->size), subblock.bytes, subblock.size);
|
||||||
subblock.bytes, subblock.size);
|
|
||||||
metadata->bytes = tmp;
|
metadata->bytes = tmp;
|
||||||
metadata->size += subblock.size;
|
metadata->size += subblock.size;
|
||||||
}
|
}
|
||||||
@@ -235,8 +230,8 @@ int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClearRectangle(WebPPicture* const picture,
|
static void ClearRectangle(WebPPicture* const picture, int left, int top,
|
||||||
int left, int top, int width, int height) {
|
int width, int height) {
|
||||||
int i, j;
|
int i, j;
|
||||||
const size_t stride = picture->argb_stride;
|
const size_t stride = picture->argb_stride;
|
||||||
uint32_t* dst = picture->argb + top * stride + left;
|
uint32_t* dst = picture->argb + top * stride + left;
|
||||||
@@ -247,8 +242,8 @@ static void ClearRectangle(WebPPicture* const picture,
|
|||||||
|
|
||||||
void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) {
|
void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) {
|
||||||
if (rect != NULL) {
|
if (rect != NULL) {
|
||||||
ClearRectangle(pic, rect->x_offset, rect->y_offset,
|
ClearRectangle(pic, rect->x_offset, rect->y_offset, rect->width,
|
||||||
rect->width, rect->height);
|
rect->height);
|
||||||
} else {
|
} else {
|
||||||
ClearRectangle(pic, 0, 0, pic->width, pic->height);
|
ClearRectangle(pic, 0, 0, pic->width, pic->height);
|
||||||
}
|
}
|
||||||
@@ -266,15 +261,14 @@ void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
|
|||||||
GIFClearPic(curr_canvas, rect);
|
GIFClearPic(curr_canvas, rect);
|
||||||
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
||||||
const size_t src_stride = prev_canvas->argb_stride;
|
const size_t src_stride = prev_canvas->argb_stride;
|
||||||
const uint32_t* const src = prev_canvas->argb + rect->x_offset
|
const uint32_t* const src =
|
||||||
+ rect->y_offset * src_stride;
|
prev_canvas->argb + rect->x_offset + rect->y_offset * src_stride;
|
||||||
const size_t dst_stride = curr_canvas->argb_stride;
|
const size_t dst_stride = curr_canvas->argb_stride;
|
||||||
uint32_t* const dst = curr_canvas->argb + rect->x_offset
|
uint32_t* const dst =
|
||||||
+ rect->y_offset * dst_stride;
|
curr_canvas->argb + rect->x_offset + rect->y_offset * dst_stride;
|
||||||
assert(prev_canvas != NULL);
|
assert(prev_canvas != NULL);
|
||||||
WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride),
|
WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride), (uint8_t*)dst,
|
||||||
(uint8_t*)dst, (int)(4 * dst_stride),
|
(int)(4 * dst_stride), 4 * rect->width, rect->height);
|
||||||
4 * rect->width, rect->height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,11 +291,11 @@ void GIFBlendFrames(const WebPPicture* const src,
|
|||||||
|
|
||||||
void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
||||||
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
||||||
#if LOCAL_GIF_PREREQ(4,2)
|
#if LOCAL_GIF_PREREQ(4, 2)
|
||||||
#if LOCAL_GIF_PREREQ(5,0)
|
#if LOCAL_GIF_PREREQ(5, 0)
|
||||||
// Static string actually, hence the const char* cast.
|
// Static string actually, hence the const char* cast.
|
||||||
const char* error_str = (const char*)GifErrorString(
|
const char* error_str =
|
||||||
(gif == NULL) ? gif_error : gif->Error);
|
(const char*)GifErrorString((gif == NULL) ? gif_error : gif->Error);
|
||||||
#else
|
#else
|
||||||
const char* error_str = (const char*)GifErrorString();
|
const char* error_str = (const char*)GifErrorString();
|
||||||
(void)gif;
|
(void)gif;
|
||||||
@@ -319,7 +313,8 @@ void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
|||||||
#else // !WEBP_HAVE_GIF
|
#else // !WEBP_HAVE_GIF
|
||||||
|
|
||||||
static void ErrorGIFNotAvailable(void) {
|
static void ErrorGIFNotAvailable(void) {
|
||||||
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
|
fprintf(stderr,
|
||||||
|
"GIF support not compiled. Please install the libgif-dev "
|
||||||
"package before building.\n");
|
"package before building.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,11 @@ extern "C" {
|
|||||||
|
|
||||||
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
||||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
#define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_PREREQ(maj, min) \
|
#define LOCAL_GIF_PREREQ(maj, min) (LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
||||||
(LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
|
||||||
#else
|
#else
|
||||||
# define LOCAL_GIF_VERSION 0
|
#define LOCAL_GIF_VERSION 0
|
||||||
# define LOCAL_GIF_PREREQ(maj, min) 0
|
#define LOCAL_GIF_PREREQ(maj, min) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GIF_INDEX_INVALID (-1)
|
#define GIF_INDEX_INVALID (-1)
|
||||||
|
|||||||
@@ -43,14 +43,18 @@ static void Help(void) {
|
|||||||
|
|
||||||
printf("File-level options (only used at the start of compression):\n");
|
printf("File-level options (only used at the start of compression):\n");
|
||||||
printf(" -min_size ............ minimize size\n");
|
printf(" -min_size ............ minimize size\n");
|
||||||
printf(" -kmax <int> .......... maximum number of frame between key-frames\n"
|
printf(
|
||||||
|
" -kmax <int> .......... maximum number of frame between key-frames\n"
|
||||||
" (0=only keyframes)\n");
|
" (0=only keyframes)\n");
|
||||||
printf(" -kmin <int> .......... minimum number of frame between key-frames\n"
|
printf(
|
||||||
|
" -kmin <int> .......... minimum number of frame between key-frames\n"
|
||||||
" (0=disable key-frames altogether)\n");
|
" (0=disable key-frames altogether)\n");
|
||||||
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
|
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
|
||||||
printf(" -near_lossless <int> . use near-lossless image preprocessing\n"
|
printf(
|
||||||
|
" -near_lossless <int> . use near-lossless image preprocessing\n"
|
||||||
" (0..100=off), default=100\n");
|
" (0..100=off), default=100\n");
|
||||||
printf(" -sharp_yuv ........... use sharper (and slower) RGB->YUV "
|
printf(
|
||||||
|
" -sharp_yuv ........... use sharper (and slower) RGB->YUV "
|
||||||
"conversion\n "
|
"conversion\n "
|
||||||
"(lossy only)\n");
|
"(lossy only)\n");
|
||||||
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
|
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
|
||||||
@@ -64,19 +68,24 @@ static void Help(void) {
|
|||||||
printf(" -lossless ............ use lossless mode (default)\n");
|
printf(" -lossless ............ use lossless mode (default)\n");
|
||||||
printf(" -lossy ............... use lossy mode\n");
|
printf(" -lossy ............... use lossy mode\n");
|
||||||
printf(" -q <float> ........... quality\n");
|
printf(" -q <float> ........... quality\n");
|
||||||
printf(" -m <int> ............. compression method (0=fast, 6=slowest), "
|
printf(
|
||||||
|
" -m <int> ............. compression method (0=fast, 6=slowest), "
|
||||||
"default=4\n");
|
"default=4\n");
|
||||||
printf(" -exact, -noexact ..... preserve or alter RGB values in transparent "
|
printf(
|
||||||
|
" -exact, -noexact ..... preserve or alter RGB values in transparent "
|
||||||
"area\n"
|
"area\n"
|
||||||
" (default: -noexact, may cause artifacts\n"
|
" (default: -noexact, may cause artifacts\n"
|
||||||
" with lossy animations)\n");
|
" with lossy animations)\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
|
printf(
|
||||||
|
"example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
|
||||||
" -d 80 in2.tiff -o out.webp\n");
|
" -d 80 in2.tiff -o out.webp\n");
|
||||||
printf("\nNote: if a single file name is passed as the argument, the "
|
printf(
|
||||||
|
"\nNote: if a single file name is passed as the argument, the "
|
||||||
"arguments will be\n");
|
"arguments will be\n");
|
||||||
printf("tokenized from this file. The file name must not start with "
|
printf(
|
||||||
|
"tokenized from this file. The file name must not start with "
|
||||||
"the character '-'.\n");
|
"the character '-'.\n");
|
||||||
printf("\nSupported input formats:\n %s\n",
|
printf("\nSupported input formats:\n %s\n",
|
||||||
WebPGetEnabledInputFileFormats());
|
WebPGetEnabledInputFileFormats());
|
||||||
@@ -127,7 +136,7 @@ static int SetLoopCount(int loop_count, WebPData* const webp_data) {
|
|||||||
ok = (err == WEBP_MUX_OK);
|
ok = (err == WEBP_MUX_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
End:
|
End:
|
||||||
WebPMuxDelete(mux);
|
WebPMuxDelete(mux);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Error during loop-count setting\n");
|
fprintf(stderr, "Error during loop-count setting\n");
|
||||||
@@ -166,8 +175,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
argv = cmd_args.argv;
|
argv = cmd_args.argv;
|
||||||
|
|
||||||
WebPDataInit(&webp_data);
|
WebPDataInit(&webp_data);
|
||||||
if (!WebPAnimEncoderOptionsInit(&anim_config) ||
|
if (!WebPAnimEncoderOptionsInit(&anim_config) || !WebPConfigInit(&config) ||
|
||||||
!WebPConfigInit(&config) ||
|
|
||||||
!WebPPictureInit(&pic)) {
|
!WebPPictureInit(&pic)) {
|
||||||
fprintf(stderr, "Library version mismatch!\n");
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
ok = 0;
|
ok = 0;
|
||||||
@@ -298,7 +306,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
ok = (width == pic.width && height == pic.height);
|
ok = (width == pic.width && height == pic.height);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Frame #%d dimension mismatched! "
|
fprintf(stderr,
|
||||||
|
"Frame #%d dimension mismatched! "
|
||||||
"Got %d x %d. Was expecting %d x %d.\n",
|
"Got %d x %d. Was expecting %d x %d.\n",
|
||||||
pic_num, pic.width, pic.height, width, height);
|
pic_num, pic.width, pic.height, width, height);
|
||||||
}
|
}
|
||||||
@@ -314,8 +323,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
if (!ok) goto End;
|
if (!ok) goto End;
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n",
|
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n", pic_num,
|
||||||
pic_num, timestamp_ms, GET_WARGV_SHIFTED(argv, c));
|
timestamp_ms, GET_WARGV_SHIFTED(argv, c));
|
||||||
}
|
}
|
||||||
timestamp_ms += duration;
|
timestamp_ms += duration;
|
||||||
++pic_num;
|
++pic_num;
|
||||||
@@ -323,8 +332,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
for (c = last_input_index + 1; c < argc; ++c) {
|
for (c = last_input_index + 1; c < argc; ++c) {
|
||||||
if (argv[c] != NULL) {
|
if (argv[c] != NULL) {
|
||||||
fprintf(stderr, "Warning: unused option [%s]!"
|
fprintf(stderr,
|
||||||
" Frame options go before the input frame.\n", argv[c]);
|
"Warning: unused option [%s]!"
|
||||||
|
" Frame options go before the input frame.\n",
|
||||||
|
argv[c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +346,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
fprintf(stderr, "Error during final animation assembly.\n");
|
fprintf(stderr, "Error during final animation assembly.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
End:
|
End:
|
||||||
// free resources
|
// free resources
|
||||||
WebPAnimEncoderDelete(enc);
|
WebPAnimEncoderDelete(enc);
|
||||||
|
|
||||||
@@ -353,8 +364,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
fprintf(stderr, "[%d frames, %u bytes].\n",
|
fprintf(stderr, "[%d frames, %u bytes].\n", pic_num,
|
||||||
pic_num, (unsigned int)webp_data.size);
|
(unsigned int)webp_data.size);
|
||||||
}
|
}
|
||||||
WebPDataClear(&webp_data);
|
WebPDataClear(&webp_data);
|
||||||
ExUtilDeleteCommandLineArguments(&cmd_args);
|
ExUtilDeleteCommandLineArguments(&cmd_args);
|
||||||
|
|||||||
@@ -28,16 +28,12 @@ static WEBP_INLINE void StopwatchReset(Stopwatch* watch) {
|
|||||||
static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
|
static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
|
||||||
const LARGE_INTEGER old_value = *watch;
|
const LARGE_INTEGER old_value = *watch;
|
||||||
LARGE_INTEGER freq;
|
LARGE_INTEGER freq;
|
||||||
if (!QueryPerformanceCounter(watch))
|
if (!QueryPerformanceCounter(watch)) return 0.0;
|
||||||
return 0.0;
|
if (!QueryPerformanceFrequency(&freq)) return 0.0;
|
||||||
if (!QueryPerformanceFrequency(&freq))
|
if (freq.QuadPart == 0) return 0.0;
|
||||||
return 0.0;
|
|
||||||
if (freq.QuadPart == 0)
|
|
||||||
return 0.0;
|
|
||||||
return (watch->QuadPart - old_value.QuadPart) / (double)freq.QuadPart;
|
return (watch->QuadPart - old_value.QuadPart) / (double)freq.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else /* !_WIN32 */
|
#else /* !_WIN32 */
|
||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|||||||
@@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
#include <shellapi.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellapi.h>
|
|
||||||
|
|
||||||
// Create a wchar_t array containing Unicode parameters.
|
// Create a wchar_t array containing Unicode parameters.
|
||||||
#define INIT_WARGV(ARGC, ARGV) \
|
#define INIT_WARGV(ARGC, ARGV) \
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include <gif_lib.h>
|
#include <gif_lib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "./gifdec.h"
|
#include "./gifdec.h"
|
||||||
|
|
||||||
#if !defined(STDIN_FILENO)
|
#if !defined(STDIN_FILENO)
|
||||||
|
|||||||
@@ -38,12 +38,11 @@
|
|||||||
#include <qcms.h>
|
#include <qcms.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "webp/demux.h"
|
|
||||||
|
|
||||||
#include "../examples/example_util.h"
|
#include "../examples/example_util.h"
|
||||||
#include "../imageio/imageio_util.h"
|
#include "../imageio/imageio_util.h"
|
||||||
#include "./unicode.h"
|
#include "./unicode.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "webp/demux.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -135,9 +134,8 @@ static int ApplyColorProfile(const WebPData* const profile,
|
|||||||
}
|
}
|
||||||
|
|
||||||
qcms_profile_precache_output_transform(output_profile);
|
qcms_profile_precache_output_transform(output_profile);
|
||||||
transform = qcms_transform_create(input_profile, input_type,
|
transform = qcms_transform_create(input_profile, input_type, output_profile,
|
||||||
output_profile, output_type,
|
output_type, intent);
|
||||||
intent);
|
|
||||||
if (transform == NULL) {
|
if (transform == NULL) {
|
||||||
fprintf(stderr, "Error creating color transform!\n");
|
fprintf(stderr, "Error creating color transform!\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
@@ -149,7 +147,7 @@ static int ApplyColorProfile(const WebPData* const profile,
|
|||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
if (input_profile != NULL) qcms_profile_release(input_profile);
|
if (input_profile != NULL) qcms_profile_release(input_profile);
|
||||||
if (output_profile != NULL) qcms_profile_release(output_profile);
|
if (output_profile != NULL) qcms_profile_release(output_profile);
|
||||||
if (transform != NULL) qcms_transform_release(transform);
|
if (transform != NULL) qcms_transform_release(transform);
|
||||||
@@ -172,8 +170,8 @@ static int Decode(void) { // Fills kParams.curr_frame
|
|||||||
|
|
||||||
ClearPreviousPic();
|
ClearPreviousPic();
|
||||||
output_buffer->colorspace = MODE_RGBA;
|
output_buffer->colorspace = MODE_RGBA;
|
||||||
ok = (WebPDecode(curr->fragment.bytes, curr->fragment.size,
|
ok = (WebPDecode(curr->fragment.bytes, curr->fragment.size, config) ==
|
||||||
config) == VP8_STATUS_OK);
|
VP8_STATUS_OK);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Decoding of frame #%d failed!\n", curr->frame_num);
|
fprintf(stderr, "Decoding of frame #%d failed!\n", curr->frame_num);
|
||||||
} else {
|
} else {
|
||||||
@@ -341,8 +339,7 @@ static void DrawBackground(void) {
|
|||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
|
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
|
||||||
GetColorf(kParams.bg_color, 8),
|
GetColorf(kParams.bg_color, 8), GetColorf(kParams.bg_color, 0),
|
||||||
GetColorf(kParams.bg_color, 0),
|
|
||||||
GetColorf(kParams.bg_color, 24));
|
GetColorf(kParams.bg_color, 24));
|
||||||
glRecti(-1, -1, +1, +1);
|
glRecti(-1, -1, +1, +1);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
@@ -402,8 +399,7 @@ static void HandleDisplay(void) {
|
|||||||
|
|
||||||
*prev = *curr;
|
*prev = *curr;
|
||||||
|
|
||||||
glDrawPixels(pic->width, pic->height,
|
glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
|
||||||
(GLvoid*)pic->u.RGBA.rgba);
|
(GLvoid*)pic->u.RGBA.rgba);
|
||||||
if (kParams.print_info) {
|
if (kParams.print_info) {
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
@@ -417,8 +413,8 @@ static void HandleDisplay(void) {
|
|||||||
glRasterPos2f(-0.95f, 0.80f);
|
glRasterPos2f(-0.95f, 0.80f);
|
||||||
PrintString(tmp);
|
PrintString(tmp);
|
||||||
if (curr->x_offset != 0 || curr->y_offset != 0) {
|
if (curr->x_offset != 0 || curr->y_offset != 0) {
|
||||||
snprintf(tmp, sizeof(tmp), " (offset:%d,%d)",
|
snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", curr->x_offset,
|
||||||
curr->x_offset, curr->y_offset);
|
curr->y_offset);
|
||||||
glRasterPos2f(-0.95f, 0.70f);
|
glRasterPos2f(-0.95f, 0.70f);
|
||||||
PrintString(tmp);
|
PrintString(tmp);
|
||||||
}
|
}
|
||||||
@@ -571,8 +567,8 @@ int main(int argc, char* argv[]) {
|
|||||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ImgIoUtilReadFile(kParams.file_name,
|
if (!ImgIoUtilReadFile(kParams.file_name, &kParams.data.bytes,
|
||||||
&kParams.data.bytes, &kParams.data.size)) {
|
&kParams.data.size)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +599,8 @@ int main(int argc, char* argv[]) {
|
|||||||
if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error;
|
if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error;
|
||||||
printf("VP8X: Found color profile\n");
|
printf("VP8X: Found color profile\n");
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "Warning: color profile present, but qcms is unavailable!\n"
|
fprintf(stderr,
|
||||||
|
"Warning: color profile present, but qcms is unavailable!\n"
|
||||||
"Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS "
|
"Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS "
|
||||||
"before building.\n");
|
"before building.\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -614,8 +611,8 @@ int main(int argc, char* argv[]) {
|
|||||||
kParams.has_animation = (curr->num_frames > 1);
|
kParams.has_animation = (curr->num_frames > 1);
|
||||||
kParams.loop_count = (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT);
|
kParams.loop_count = (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT);
|
||||||
kParams.bg_color = WebPDemuxGetI(kParams.dmux, WEBP_FF_BACKGROUND_COLOR);
|
kParams.bg_color = WebPDemuxGetI(kParams.dmux, WEBP_FF_BACKGROUND_COLOR);
|
||||||
printf("VP8X: Found %d images in file (loop count = %d)\n",
|
printf("VP8X: Found %d images in file (loop count = %d)\n", curr->num_frames,
|
||||||
curr->num_frames, kParams.loop_count);
|
kParams.loop_count);
|
||||||
|
|
||||||
// Decode first frame
|
// Decode first frame
|
||||||
if (!Decode()) goto Error;
|
if (!Decode()) goto Error;
|
||||||
@@ -645,7 +642,7 @@ int main(int argc, char* argv[]) {
|
|||||||
ClearParams();
|
ClearParams();
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
ClearParams();
|
ClearParams();
|
||||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,25 +47,13 @@
|
|||||||
++webp_info->num_warnings; \
|
++webp_info->num_warnings; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static const char* const kFormats[3] = {
|
static const char* const kFormats[3] = {"Unknown", "Lossy", "Lossless"};
|
||||||
"Unknown",
|
|
||||||
"Lossy",
|
|
||||||
"Lossless"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char* const kLosslessTransforms[4] = {
|
static const char* const kLosslessTransforms[4] = {
|
||||||
"Predictor",
|
"Predictor", "Cross Color", "Subtract Green", "Color Indexing"};
|
||||||
"Cross Color",
|
|
||||||
"Subtract Green",
|
|
||||||
"Color Indexing"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char* const kAlphaFilterMethods[4] = {
|
static const char* const kAlphaFilterMethods[4] = {"None", "Horizontal",
|
||||||
"None",
|
"Vertical", "Gradient"};
|
||||||
"Horizontal",
|
|
||||||
"Vertical",
|
|
||||||
"Gradient"
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WEBP_INFO_OK = 0,
|
WEBP_INFO_OK = 0,
|
||||||
@@ -129,15 +117,15 @@ static void WebPInfoInit(WebPInfo* const webp_info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t kWebPChunkTags[CHUNK_TYPES] = {
|
static const uint32_t kWebPChunkTags[CHUNK_TYPES] = {
|
||||||
MKFOURCC('V', 'P', '8', ' '),
|
MKFOURCC('V', 'P', '8', ' '), //
|
||||||
MKFOURCC('V', 'P', '8', 'L'),
|
MKFOURCC('V', 'P', '8', 'L'), //
|
||||||
MKFOURCC('V', 'P', '8', 'X'),
|
MKFOURCC('V', 'P', '8', 'X'), //
|
||||||
MKFOURCC('A', 'L', 'P', 'H'),
|
MKFOURCC('A', 'L', 'P', 'H'), //
|
||||||
MKFOURCC('A', 'N', 'I', 'M'),
|
MKFOURCC('A', 'N', 'I', 'M'), //
|
||||||
MKFOURCC('A', 'N', 'M', 'F'),
|
MKFOURCC('A', 'N', 'M', 'F'), //
|
||||||
MKFOURCC('I', 'C', 'C', 'P'),
|
MKFOURCC('I', 'C', 'C', 'P'), //
|
||||||
MKFOURCC('E', 'X', 'I', 'F'),
|
MKFOURCC('E', 'X', 'I', 'F'), //
|
||||||
MKFOURCC('X', 'M', 'P', ' '),
|
MKFOURCC('X', 'M', 'P', ' '), //
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -200,9 +188,7 @@ static const uint8_t* GetBuffer(MemBuffer* const mem) {
|
|||||||
return mem->buf + mem->start;
|
return mem->buf + mem->start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Skip(MemBuffer* const mem, size_t size) {
|
static void Skip(MemBuffer* const mem, size_t size) { mem->start += size; }
|
||||||
mem->start += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ReadMemBufLE32(MemBuffer* const mem) {
|
static uint32_t ReadMemBufLE32(MemBuffer* const mem) {
|
||||||
const uint8_t* const data = mem->buf + mem->start;
|
const uint8_t* const data = mem->buf + mem->start;
|
||||||
@@ -266,7 +252,8 @@ static WebPInfoStatus ParseLossySegmentHeader(const WebPInfo* const webp_info,
|
|||||||
int update_map, update_data;
|
int update_map, update_data;
|
||||||
GET_BITS(update_map, 1);
|
GET_BITS(update_map, 1);
|
||||||
GET_BITS(update_data, 1);
|
GET_BITS(update_data, 1);
|
||||||
printf(" Update map: %d\n"
|
printf(
|
||||||
|
" Update map: %d\n"
|
||||||
" Update data: %d\n",
|
" Update data: %d\n",
|
||||||
update_map, update_data);
|
update_map, update_data);
|
||||||
if (update_data) {
|
if (update_data) {
|
||||||
@@ -298,8 +285,8 @@ static WebPInfoStatus ParseLossySegmentHeader(const WebPInfo* const webp_info,
|
|||||||
GET_BITS(bit, 1);
|
GET_BITS(bit, 1);
|
||||||
if (bit) GET_BITS(prob_segment[i], 8);
|
if (bit) GET_BITS(prob_segment[i], 8);
|
||||||
}
|
}
|
||||||
printf(" Prob segment: %d %d %d\n",
|
printf(" Prob segment: %d %d %d\n", prob_segment[0], prob_segment[1],
|
||||||
prob_segment[0], prob_segment[1], prob_segment[2]);
|
prob_segment[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WEBP_INFO_OK;
|
return WEBP_INFO_OK;
|
||||||
@@ -371,7 +358,8 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
|
|||||||
LOG_ERROR("Invalid lossy bitstream signature.");
|
LOG_ERROR("Invalid lossy bitstream signature.");
|
||||||
return WEBP_INFO_BITSTREAM_ERROR;
|
return WEBP_INFO_BITSTREAM_ERROR;
|
||||||
}
|
}
|
||||||
printf(" Width: %d\n"
|
printf(
|
||||||
|
" Width: %d\n"
|
||||||
" X scale: %d\n"
|
" X scale: %d\n"
|
||||||
" Height: %d\n"
|
" Height: %d\n"
|
||||||
" Y scale: %d\n",
|
" Y scale: %d\n",
|
||||||
@@ -499,7 +487,8 @@ static WebPInfoStatus ParseLosslessTransform(WebPInfo* const webp_info,
|
|||||||
n_colors += 1;
|
n_colors += 1;
|
||||||
printf(" No. of colors: %d\n", n_colors);
|
printf(" No. of colors: %d\n", n_colors);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WEBP_INFO_OK;
|
return WEBP_INFO_OK;
|
||||||
@@ -556,8 +545,8 @@ static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data,
|
|||||||
const int pre_processing = (data[0] >> 4) & 0x03;
|
const int pre_processing = (data[0] >> 4) & 0x03;
|
||||||
const int reserved_bits = (data[0] >> 6) & 0x03;
|
const int reserved_bits = (data[0] >> 6) & 0x03;
|
||||||
printf(" Compression: %d\n", compression_method);
|
printf(" Compression: %d\n", compression_method);
|
||||||
printf(" Filter: %s (%d)\n",
|
printf(" Filter: %s (%d)\n", kAlphaFilterMethods[filter],
|
||||||
kAlphaFilterMethods[filter], filter);
|
filter);
|
||||||
printf(" Pre-processing: %d\n", pre_processing);
|
printf(" Pre-processing: %d\n", pre_processing);
|
||||||
if (compression_method > ALPHA_LOSSLESS_COMPRESSION) {
|
if (compression_method > ALPHA_LOSSLESS_COMPRESSION) {
|
||||||
LOG_ERROR("Invalid Alpha compression method.");
|
LOG_ERROR("Invalid Alpha compression method.");
|
||||||
@@ -642,7 +631,7 @@ static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info,
|
|||||||
LOG_ERROR("Size of chunk payload is over limit.");
|
LOG_ERROR("Size of chunk payload is over limit.");
|
||||||
return WEBP_INFO_INVALID_PARAM;
|
return WEBP_INFO_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
if (payload_size_padded > MemDataSize(mem)){
|
if (payload_size_padded > MemDataSize(mem)) {
|
||||||
LOG_ERROR("Truncated data detected when parsing chunk payload.");
|
LOG_ERROR("Truncated data detected when parsing chunk payload.");
|
||||||
return WEBP_INFO_TRUNCATED_DATA;
|
return WEBP_INFO_TRUNCATED_DATA;
|
||||||
}
|
}
|
||||||
@@ -695,8 +684,8 @@ static WebPInfoStatus ProcessVP8XChunk(const ChunkData* const chunk_data,
|
|||||||
(webp_info->feature_flags & EXIF_FLAG) != 0,
|
(webp_info->feature_flags & EXIF_FLAG) != 0,
|
||||||
(webp_info->feature_flags & XMP_FLAG) != 0,
|
(webp_info->feature_flags & XMP_FLAG) != 0,
|
||||||
(webp_info->feature_flags & ANIMATION_FLAG) != 0);
|
(webp_info->feature_flags & ANIMATION_FLAG) != 0);
|
||||||
printf(" Canvas size %d x %d\n",
|
printf(" Canvas size %d x %d\n", webp_info->canvas_width,
|
||||||
webp_info->canvas_width, webp_info->canvas_height);
|
webp_info->canvas_height);
|
||||||
}
|
}
|
||||||
if (webp_info->canvas_width > MAX_CANVAS_SIZE) {
|
if (webp_info->canvas_width > MAX_CANVAS_SIZE) {
|
||||||
LOG_WARN("Canvas width is out of range in VP8X chunk.");
|
LOG_WARN("Canvas width is out of range in VP8X chunk.");
|
||||||
@@ -727,10 +716,8 @@ static WebPInfoStatus ProcessANIMChunk(const ChunkData* const chunk_data,
|
|||||||
++webp_info->chunk_counts[CHUNK_ANIM];
|
++webp_info->chunk_counts[CHUNK_ANIM];
|
||||||
if (!webp_info->quiet) {
|
if (!webp_info->quiet) {
|
||||||
printf(" Background color:(ARGB) %02x %02x %02x %02x\n",
|
printf(" Background color:(ARGB) %02x %02x %02x %02x\n",
|
||||||
(webp_info->bgcolor >> 24) & 0xff,
|
(webp_info->bgcolor >> 24) & 0xff, (webp_info->bgcolor >> 16) & 0xff,
|
||||||
(webp_info->bgcolor >> 16) & 0xff,
|
(webp_info->bgcolor >> 8) & 0xff, webp_info->bgcolor & 0xff);
|
||||||
(webp_info->bgcolor >> 8) & 0xff,
|
|
||||||
webp_info->bgcolor & 0xff);
|
|
||||||
printf(" Loop count : %d\n", webp_info->loop_count);
|
printf(" Loop count : %d\n", webp_info->loop_count);
|
||||||
}
|
}
|
||||||
if (webp_info->loop_count > MAX_LOOP_COUNT) {
|
if (webp_info->loop_count > MAX_LOOP_COUNT) {
|
||||||
@@ -765,7 +752,8 @@ static WebPInfoStatus ProcessANMFChunk(const ChunkData* const chunk_data,
|
|||||||
blend = (temp >> 1) & 1;
|
blend = (temp >> 1) & 1;
|
||||||
++webp_info->chunk_counts[CHUNK_ANMF];
|
++webp_info->chunk_counts[CHUNK_ANMF];
|
||||||
if (!webp_info->quiet) {
|
if (!webp_info->quiet) {
|
||||||
printf(" Offset_X: %d\n Offset_Y: %d\n Width: %d\n Height: %d\n"
|
printf(
|
||||||
|
" Offset_X: %d\n Offset_Y: %d\n Width: %d\n Height: %d\n"
|
||||||
" Duration: %d\n Dispose: %d\n Blend: %d\n",
|
" Duration: %d\n Dispose: %d\n Blend: %d\n",
|
||||||
offset_x, offset_y, width, height, duration, dispose, blend);
|
offset_x, offset_y, width, height, duration, dispose, blend);
|
||||||
}
|
}
|
||||||
@@ -804,7 +792,8 @@ static WebPInfoStatus ProcessImageChunk(const ChunkData* const chunk_data,
|
|||||||
}
|
}
|
||||||
if (!webp_info->quiet) {
|
if (!webp_info->quiet) {
|
||||||
assert(features.format >= 0 && features.format <= 2);
|
assert(features.format >= 0 && features.format <= 2);
|
||||||
printf(" Width: %d\n Height: %d\n Alpha: %d\n Animation: %d\n"
|
printf(
|
||||||
|
" Width: %d\n Height: %d\n Alpha: %d\n Animation: %d\n"
|
||||||
" Format: %s (%d)\n",
|
" Format: %s (%d)\n",
|
||||||
features.width, features.height, features.has_alpha,
|
features.width, features.height, features.has_alpha,
|
||||||
features.has_animation, kFormats[features.format], features.format);
|
features.has_animation, kFormats[features.format], features.format);
|
||||||
@@ -831,8 +820,7 @@ static WebPInfoStatus ProcessImageChunk(const ChunkData* const chunk_data,
|
|||||||
LOG_ERROR("Multiple VP8/VP8L chunks detected.");
|
LOG_ERROR("Multiple VP8/VP8L chunks detected.");
|
||||||
return WEBP_INFO_PARSE_ERROR;
|
return WEBP_INFO_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
if (chunk_data->id == CHUNK_VP8L &&
|
if (chunk_data->id == CHUNK_VP8L && webp_info->chunk_counts[CHUNK_ALPHA]) {
|
||||||
webp_info->chunk_counts[CHUNK_ALPHA]) {
|
|
||||||
LOG_WARN("Both VP8L and ALPH chunks are detected.");
|
LOG_WARN("Both VP8L and ALPH chunks are detected.");
|
||||||
}
|
}
|
||||||
if (webp_info->chunk_counts[CHUNK_ANIM] ||
|
if (webp_info->chunk_counts[CHUNK_ANIM] ||
|
||||||
@@ -882,7 +870,8 @@ static WebPInfoStatus ProcessALPHChunk(const ChunkData* const chunk_data,
|
|||||||
webp_info->seen_alpha_subchunk = 1;
|
webp_info->seen_alpha_subchunk = 1;
|
||||||
|
|
||||||
if (webp_info->seen_image_subchunk) {
|
if (webp_info->seen_image_subchunk) {
|
||||||
LOG_ERROR("ALPHA sub-chunk detected after VP8 sub-chunk "
|
LOG_ERROR(
|
||||||
|
"ALPHA sub-chunk detected after VP8 sub-chunk "
|
||||||
"in an ANMF chunk.");
|
"in an ANMF chunk.");
|
||||||
return WEBP_INFO_PARSE_ERROR;
|
return WEBP_INFO_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
@@ -949,9 +938,8 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
|
|||||||
((fourcc << 8) & 0xff0000) | (fourcc << 24);
|
((fourcc << 8) & 0xff0000) | (fourcc << 24);
|
||||||
#endif
|
#endif
|
||||||
memcpy(tag, &fourcc, sizeof(tag));
|
memcpy(tag, &fourcc, sizeof(tag));
|
||||||
printf("Chunk %c%c%c%c at offset %6d, length %6d\n",
|
printf("Chunk %c%c%c%c at offset %6d, length %6d\n", tag[0], tag[1],
|
||||||
tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset,
|
tag[2], tag[3], (int)chunk_data->offset, (int)chunk_data->size);
|
||||||
(int)chunk_data->size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -1060,14 +1048,14 @@ static void ShowSummary(const WebPInfo* const webp_info) {
|
|||||||
int i;
|
int i;
|
||||||
printf("Summary:\n");
|
printf("Summary:\n");
|
||||||
printf("Number of frames: %d\n", webp_info->num_frames);
|
printf("Number of frames: %d\n", webp_info->num_frames);
|
||||||
printf("Chunk type : VP8 VP8L VP8X ALPH ANIM ANMF(VP8 /VP8L/ALPH) ICCP "
|
printf(
|
||||||
|
"Chunk type : VP8 VP8L VP8X ALPH ANIM ANMF(VP8 /VP8L/ALPH) ICCP "
|
||||||
"EXIF XMP\n");
|
"EXIF XMP\n");
|
||||||
printf("Chunk counts: ");
|
printf("Chunk counts: ");
|
||||||
for (i = 0; i < CHUNK_TYPES; ++i) {
|
for (i = 0; i < CHUNK_TYPES; ++i) {
|
||||||
printf("%4d ", webp_info->chunk_counts[i]);
|
printf("%4d ", webp_info->chunk_counts[i]);
|
||||||
if (i == CHUNK_ANMF) {
|
if (i == CHUNK_ANMF) {
|
||||||
printf("%4d %4d %4d ",
|
printf("%4d %4d %4d ", webp_info->anmf_subchunk_counts[0],
|
||||||
webp_info->anmf_subchunk_counts[0],
|
|
||||||
webp_info->anmf_subchunk_counts[1],
|
webp_info->anmf_subchunk_counts[1],
|
||||||
webp_info->anmf_subchunk_counts[2]);
|
webp_info->anmf_subchunk_counts[2]);
|
||||||
}
|
}
|
||||||
@@ -1097,7 +1085,7 @@ static WebPInfoStatus AnalyzeWebP(WebPInfo* const webp_info,
|
|||||||
// Final check.
|
// Final check.
|
||||||
webp_info_status = Validate(webp_info);
|
webp_info_status = Validate(webp_info);
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
if (!webp_info->quiet) {
|
if (!webp_info->quiet) {
|
||||||
if (webp_info_status == WEBP_INFO_OK) {
|
if (webp_info_status == WEBP_INFO_OK) {
|
||||||
printf("No error detected.\n");
|
printf("No error detected.\n");
|
||||||
@@ -1112,7 +1100,8 @@ static WebPInfoStatus AnalyzeWebP(WebPInfo* const webp_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Help(void) {
|
static void Help(void) {
|
||||||
printf("Usage: webpinfo [options] in_files\n"
|
printf(
|
||||||
|
"Usage: webpinfo [options] in_files\n"
|
||||||
"Note: there could be multiple input files;\n"
|
"Note: there could be multiple input files;\n"
|
||||||
" options must come before input files.\n"
|
" options must come before input files.\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
@@ -1153,8 +1142,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
parse_bitstream = 1;
|
parse_bitstream = 1;
|
||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
const int version = WebPGetDecoderVersion();
|
const int version = WebPGetDecoderVersion();
|
||||||
printf("WebP Decoder version: %d.%d.%d\n",
|
printf("WebP Decoder version: %d.%d.%d\n", (version >> 16) & 0xff,
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
(version >> 8) & 0xff, version & 0xff);
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||||
} else { // Assume the remaining are all input files.
|
} else { // Assume the remaining are all input files.
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -106,14 +106,11 @@ typedef enum {
|
|||||||
LAST_FEATURE
|
LAST_FEATURE
|
||||||
} FeatureType;
|
} FeatureType;
|
||||||
|
|
||||||
static const char* const kFourccList[LAST_FEATURE] = {
|
static const char* const kFourccList[LAST_FEATURE] = {NULL, "EXIF", "XMP ",
|
||||||
NULL, "EXIF", "XMP ", "ICCP", "ANMF"
|
"ICCP", "ANMF"};
|
||||||
};
|
|
||||||
|
|
||||||
static const char* const kDescriptions[LAST_FEATURE] = {
|
static const char* const kDescriptions[LAST_FEATURE] = {
|
||||||
NULL, "EXIF metadata", "XMP metadata", "ICC profile",
|
NULL, "EXIF metadata", "XMP metadata", "ICC profile", "Animation frame"};
|
||||||
"Animation frame"
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CommandLineArguments cmd_args;
|
CommandLineArguments cmd_args;
|
||||||
@@ -144,8 +141,7 @@ static int CountOccurrences(const CommandLineArguments* const args,
|
|||||||
|
|
||||||
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
||||||
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
||||||
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"
|
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"};
|
||||||
};
|
|
||||||
|
|
||||||
static const char* ErrorString(WebPMuxError err) {
|
static const char* ErrorString(WebPMuxError err) {
|
||||||
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
||||||
@@ -222,8 +218,8 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
WebPMuxAnimParams params;
|
WebPMuxAnimParams params;
|
||||||
err = WebPMuxGetAnimationParams(mux, ¶ms);
|
err = WebPMuxGetAnimationParams(mux, ¶ms);
|
||||||
assert(err == WEBP_MUX_OK);
|
assert(err == WEBP_MUX_OK);
|
||||||
printf("Background color : 0x%.8X Loop Count : %d\n",
|
printf("Background color : 0x%.8X Loop Count : %d\n", params.bgcolor,
|
||||||
params.bgcolor, params.loop_count);
|
params.loop_count);
|
||||||
|
|
||||||
err = WebPMuxNumChunks(mux, id, &nFrames);
|
err = WebPMuxNumChunks(mux, id, &nFrames);
|
||||||
assert(err == WEBP_MUX_OK);
|
assert(err == WEBP_MUX_OK);
|
||||||
@@ -255,9 +251,9 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
printf("%8d %10s %5s ", frame.duration, dispose, blend);
|
printf("%8d %10s %5s ", frame.duration, dispose, blend);
|
||||||
}
|
}
|
||||||
printf("%10d %11s\n", (int)frame.bitstream.size,
|
printf("%10d %11s\n", (int)frame.bitstream.size,
|
||||||
(features.format == 1) ? "lossy" :
|
(features.format == 1) ? "lossy"
|
||||||
(features.format == 2) ? "lossless" :
|
: (features.format == 2) ? "lossless"
|
||||||
"undefined");
|
: "undefined");
|
||||||
}
|
}
|
||||||
WebPDataClear(&frame.bitstream);
|
WebPDataClear(&frame.bitstream);
|
||||||
RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i);
|
RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i);
|
||||||
@@ -305,7 +301,8 @@ static void PrintHelp(void) {
|
|||||||
printf(" webpmux -duration DURATION_OPTIONS [-duration ...]\n");
|
printf(" webpmux -duration DURATION_OPTIONS [-duration ...]\n");
|
||||||
printf(" INPUT -o OUTPUT\n");
|
printf(" INPUT -o OUTPUT\n");
|
||||||
printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n");
|
printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n");
|
||||||
printf(" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
printf(
|
||||||
|
" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
||||||
"\n");
|
"\n");
|
||||||
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
||||||
printf(" webpmux -info INPUT\n");
|
printf(" webpmux -info INPUT\n");
|
||||||
@@ -360,7 +357,8 @@ static void PrintHelp(void) {
|
|||||||
printf(" 'di' is the pause duration before next frame,\n");
|
printf(" 'di' is the pause duration before next frame,\n");
|
||||||
printf(" 'xi','yi' specify the image offset for this frame,\n");
|
printf(" 'xi','yi' specify the image offset for this frame,\n");
|
||||||
printf(" 'mi' is the dispose method for this frame (0 or 1),\n");
|
printf(" 'mi' is the dispose method for this frame (0 or 1),\n");
|
||||||
printf(" 'bi' is the blending method for this frame (+b or -b)"
|
printf(
|
||||||
|
" 'bi' is the blending method for this frame (+b or -b)"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -372,9 +370,11 @@ static void PrintHelp(void) {
|
|||||||
printf("BACKGROUND_COLOR:\n");
|
printf("BACKGROUND_COLOR:\n");
|
||||||
printf(" Background color of the canvas.\n");
|
printf(" Background color of the canvas.\n");
|
||||||
printf(" A,R,G,B\n");
|
printf(" A,R,G,B\n");
|
||||||
printf(" where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 "
|
printf(
|
||||||
|
" where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 "
|
||||||
"specifying\n");
|
"specifying\n");
|
||||||
printf(" the Alpha, Red, Green and Blue component values "
|
printf(
|
||||||
|
" the Alpha, Red, Green and Blue component values "
|
||||||
"respectively\n");
|
"respectively\n");
|
||||||
printf(" [Default: 255,255,255,255]\n");
|
printf(" [Default: 255,255,255,255]\n");
|
||||||
|
|
||||||
@@ -382,17 +382,21 @@ static void PrintHelp(void) {
|
|||||||
|
|
||||||
printf("\nNote: The nature of EXIF, XMP and ICC data is not checked");
|
printf("\nNote: The nature of EXIF, XMP and ICC data is not checked");
|
||||||
printf(" and is assumed to be\nvalid.\n");
|
printf(" and is assumed to be\nvalid.\n");
|
||||||
printf("\nNote: if a single file name is passed as the argument, the "
|
printf(
|
||||||
|
"\nNote: if a single file name is passed as the argument, the "
|
||||||
"arguments will be\n");
|
"arguments will be\n");
|
||||||
printf("tokenized from this file. The file name must not start with "
|
printf(
|
||||||
|
"tokenized from this file. The file name must not start with "
|
||||||
"the character '-'.\n");
|
"the character '-'.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
|
static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
|
||||||
if ((info->x_offset | info->y_offset) & 1) {
|
if ((info->x_offset | info->y_offset) & 1) {
|
||||||
fprintf(stderr, "Warning: odd offsets will be snapped to even values"
|
fprintf(stderr,
|
||||||
" (%d, %d) -> (%d, %d)\n", info->x_offset, info->y_offset,
|
"Warning: odd offsets will be snapped to even values"
|
||||||
info->x_offset & ~1, info->y_offset & ~1);
|
" (%d, %d) -> (%d, %d)\n",
|
||||||
|
info->x_offset, info->y_offset, info->x_offset & ~1,
|
||||||
|
info->y_offset & ~1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,8 +424,8 @@ static int WriteData(const char* filename, const WebPData* const webpdata) {
|
|||||||
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
|
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
|
||||||
WFPRINTF(stderr, "Error writing file %s!\n", (const W_CHAR*)filename);
|
WFPRINTF(stderr, "Error writing file %s!\n", (const W_CHAR*)filename);
|
||||||
} else {
|
} else {
|
||||||
WFPRINTF(stderr, "Saved file %s (%d bytes)\n",
|
WFPRINTF(stderr, "Saved file %s (%d bytes)\n", (const W_CHAR*)filename,
|
||||||
(const W_CHAR*)filename, (int)webpdata->size);
|
(int)webpdata->size);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
if (fout != stdout) fclose(fout);
|
if (fout != stdout) fclose(fout);
|
||||||
@@ -454,8 +458,8 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
|
|||||||
if (err == WEBP_MUX_OK) {
|
if (err == WEBP_MUX_OK) {
|
||||||
err = WebPMuxSetAnimationParams(new_mux, &p);
|
err = WebPMuxSetAnimationParams(new_mux, &p);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO2("Error (%s) handling animation params.\n",
|
ERROR_GOTO2("Error (%s) handling animation params.\n", ErrorString(err),
|
||||||
ErrorString(err), End);
|
End);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* it might not be an animation. Just keep moving. */
|
/* it might not be an animation. Just keep moving. */
|
||||||
@@ -473,7 +477,7 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
End:
|
End:
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
WebPMuxDelete(new_mux);
|
WebPMuxDelete(new_mux);
|
||||||
new_mux = NULL;
|
new_mux = NULL;
|
||||||
@@ -511,8 +515,7 @@ static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
|
|||||||
|
|
||||||
if (blend_method != 'b') return 0;
|
if (blend_method != 'b') return 0;
|
||||||
if (plus_minus != '-' && plus_minus != '+') return 0;
|
if (plus_minus != '-' && plus_minus != '+') return 0;
|
||||||
info->blend_method =
|
info->blend_method = (plus_minus == '+') ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND;
|
||||||
(plus_minus == '+') ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,8 +587,10 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((num_frame_args == 0) && (num_loop_args + num_bgcolor_args > 0)) {
|
if ((num_frame_args == 0) && (num_loop_args + num_bgcolor_args > 0)) {
|
||||||
ERROR_GOTO1("ERROR: Loop count and background color are relevant only in "
|
ERROR_GOTO1(
|
||||||
"case of animation.\n", ErrValidate);
|
"ERROR: Loop count and background color are relevant only in "
|
||||||
|
"case of animation.\n",
|
||||||
|
ErrValidate);
|
||||||
}
|
}
|
||||||
if (num_durations_args > 0 && num_frame_args != 0) {
|
if (num_durations_args > 0 && num_frame_args != 0) {
|
||||||
ERROR_GOTO1("ERROR: Can not combine -duration and -frame commands.\n",
|
ERROR_GOTO1("ERROR: Can not combine -duration and -frame commands.\n",
|
||||||
@@ -603,7 +608,7 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
|
|||||||
*num_feature_args = num_frame_args + num_loop_args + num_bgcolor_args;
|
*num_feature_args = num_frame_args + num_loop_args + num_bgcolor_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrValidate:
|
ErrValidate:
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -739,8 +744,8 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
|
|||||||
exit(0);
|
exit(0);
|
||||||
} else if (!strcmp(argv[i], "-version")) {
|
} else if (!strcmp(argv[i], "-version")) {
|
||||||
const int version = WebPGetMuxVersion();
|
const int version = WebPGetMuxVersion();
|
||||||
printf("%d.%d.%d\n",
|
printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff,
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
version & 0xff);
|
||||||
DeleteConfig(config);
|
DeleteConfig(config);
|
||||||
LOCAL_FREE((W_CHAR**)unicode_argv);
|
LOCAL_FREE((W_CHAR**)unicode_argv);
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -771,8 +776,9 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
|
|||||||
if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") ||
|
if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") ||
|
||||||
!strcmp(argv[i], "xmp")) {
|
!strcmp(argv[i], "xmp")) {
|
||||||
if (FEATURETYPE_IS_NIL) {
|
if (FEATURETYPE_IS_NIL) {
|
||||||
config->type = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP :
|
config->type = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP
|
||||||
(!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP;
|
: (!strcmp(argv[i], "exif")) ? FEATURE_EXIF
|
||||||
|
: FEATURE_XMP;
|
||||||
} else {
|
} else {
|
||||||
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
|
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
|
||||||
}
|
}
|
||||||
@@ -826,7 +832,7 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ErrParse:
|
ErrParse:
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -858,7 +864,7 @@ static int ValidateConfig(Config* const config) {
|
|||||||
ERROR_GOTO1("ERROR: No output file specified.\n", ErrValidate2);
|
ERROR_GOTO1("ERROR: No output file specified.\n", ErrValidate2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrValidate2:
|
ErrValidate2:
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,7 +895,7 @@ static int InitializeConfig(int argc, const char* argv[], Config* const config,
|
|||||||
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
|
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err1:
|
Err1:
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,8 +927,8 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
|
|||||||
err = WebPMuxGetFrame(mux, num, &info);
|
err = WebPMuxGetFrame(mux, num, &info);
|
||||||
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
|
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not get frame %d.\n",
|
ERROR_GOTO3("ERROR (%s): Could not get frame %d.\n", ErrorString(err), num,
|
||||||
ErrorString(err), num, ErrGet);
|
ErrGet);
|
||||||
}
|
}
|
||||||
|
|
||||||
mux_single = WebPMuxNew();
|
mux_single = WebPMuxNew();
|
||||||
@@ -939,7 +945,7 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
|
|||||||
|
|
||||||
ok = WriteWebP(mux_single, config->output);
|
ok = WriteWebP(mux_single, config->output);
|
||||||
|
|
||||||
ErrGet:
|
ErrGet:
|
||||||
WebPDataClear(&info.bitstream);
|
WebPDataClear(&info.bitstream);
|
||||||
WebPMuxDelete(mux_single);
|
WebPMuxDelete(mux_single);
|
||||||
return ok && !parse_error;
|
return ok && !parse_error;
|
||||||
@@ -966,8 +972,8 @@ static int Process(const Config* config) {
|
|||||||
case FEATURE_XMP:
|
case FEATURE_XMP:
|
||||||
err = WebPMuxGetChunk(mux, kFourccList[config->type], &chunk);
|
err = WebPMuxGetChunk(mux, kFourccList[config->type], &chunk);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not get the %s.\n",
|
ERROR_GOTO3("ERROR (%s): Could not get the %s.\n", ErrorString(err),
|
||||||
ErrorString(err), kDescriptions[config->type], Err2);
|
kDescriptions[config->type], Err2);
|
||||||
}
|
}
|
||||||
ok = WriteData(config->output, &chunk);
|
ok = WriteData(config->output, &chunk);
|
||||||
break;
|
break;
|
||||||
@@ -982,7 +988,7 @@ static int Process(const Config* config) {
|
|||||||
switch (config->type) {
|
switch (config->type) {
|
||||||
case FEATURE_ANMF: {
|
case FEATURE_ANMF: {
|
||||||
int i;
|
int i;
|
||||||
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
WebPMuxAnimParams params = {0xFFFFFFFF, 0};
|
||||||
mux = WebPMuxNew();
|
mux = WebPMuxNew();
|
||||||
if (mux == NULL) {
|
if (mux == NULL) {
|
||||||
ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n",
|
ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n",
|
||||||
@@ -1008,8 +1014,10 @@ static int Process(const Config* config) {
|
|||||||
// Note: This is only a 'necessary' condition for loop_count
|
// Note: This is only a 'necessary' condition for loop_count
|
||||||
// to be valid. The 'sufficient' conditioned in checked in
|
// to be valid. The 'sufficient' conditioned in checked in
|
||||||
// WebPMuxSetAnimationParams() method called later.
|
// WebPMuxSetAnimationParams() method called later.
|
||||||
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to "
|
ERROR_GOTO1(
|
||||||
"65535.\n", Err2);
|
"ERROR: Loop count must be in the range 0 to "
|
||||||
|
"65535.\n",
|
||||||
|
Err2);
|
||||||
}
|
}
|
||||||
ok = !parse_error;
|
ok = !parse_error;
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
@@ -1031,8 +1039,10 @@ static int Process(const Config* config) {
|
|||||||
err = WebPMuxPushFrame(mux, &frame, 1);
|
err = WebPMuxPushFrame(mux, &frame, 1);
|
||||||
WebPDataClear(&frame.bitstream);
|
WebPDataClear(&frame.bitstream);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not add a frame at index %d."
|
ERROR_GOTO3(
|
||||||
"\n", ErrorString(err), i, Err2);
|
"ERROR (%s): Could not add a frame at index %d."
|
||||||
|
"\n",
|
||||||
|
ErrorString(err), i, Err2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1060,13 +1070,13 @@ static int Process(const Config* config) {
|
|||||||
err = WebPMuxSetChunk(mux, kFourccList[config->type], &chunk, 1);
|
err = WebPMuxSetChunk(mux, kFourccList[config->type], &chunk, 1);
|
||||||
WebPDataClear(&chunk);
|
WebPDataClear(&chunk);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n",
|
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n", ErrorString(err),
|
||||||
ErrorString(err), kDescriptions[config->type], Err2);
|
kDescriptions[config->type], Err2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FEATURE_LOOP: {
|
case FEATURE_LOOP: {
|
||||||
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
WebPMuxAnimParams params = {0xFFFFFFFF, 0};
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
const int loop_count =
|
const int loop_count =
|
||||||
ExUtilGetInt(config->args[0].params, 10, &parse_error);
|
ExUtilGetInt(config->args[0].params, 10, &parse_error);
|
||||||
@@ -1091,12 +1101,11 @@ static int Process(const Config* config) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FEATURE_BGCOLOR: {
|
case FEATURE_BGCOLOR: {
|
||||||
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
WebPMuxAnimParams params = {0xFFFFFFFF, 0};
|
||||||
uint32_t bgcolor;
|
uint32_t bgcolor;
|
||||||
ok = ParseBgcolorArgs(config->args[0].params, &bgcolor);
|
ok = ParseBgcolorArgs(config->args[0].params, &bgcolor);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
ERROR_GOTO1("ERROR: Could not parse the background color.\n",
|
ERROR_GOTO1("ERROR: Could not parse the background color.\n", Err2);
|
||||||
Err2);
|
|
||||||
}
|
}
|
||||||
ok = CreateMux(config->input, &mux);
|
ok = CreateMux(config->input, &mux);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
@@ -1132,7 +1141,8 @@ static int Process(const Config* config) {
|
|||||||
ERROR_GOTO1("ERROR: can not parse the number of frames.\n", Err2);
|
ERROR_GOTO1("ERROR: can not parse the number of frames.\n", Err2);
|
||||||
}
|
}
|
||||||
if (num_frames == 0) {
|
if (num_frames == 0) {
|
||||||
fprintf(stderr, "Doesn't look like the source is animated. "
|
fprintf(stderr,
|
||||||
|
"Doesn't look like the source is animated. "
|
||||||
"Skipping duration setting.\n");
|
"Skipping duration setting.\n");
|
||||||
ok = WriteWebP(mux, config->output);
|
ok = WriteWebP(mux, config->output);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
@@ -1150,8 +1160,8 @@ static int Process(const Config* config) {
|
|||||||
int k;
|
int k;
|
||||||
int args[3];
|
int args[3];
|
||||||
int duration, start, end;
|
int duration, start, end;
|
||||||
const int nb_args = ExUtilGetInts(config->args[i].params,
|
const int nb_args =
|
||||||
10, 3, args);
|
ExUtilGetInts(config->args[i].params, 10, 3, args);
|
||||||
ok = (nb_args >= 1);
|
ok = (nb_args >= 1);
|
||||||
if (!ok) goto Err3;
|
if (!ok) goto Err3;
|
||||||
duration = args[0];
|
duration = args[0];
|
||||||
@@ -1212,8 +1222,8 @@ static int Process(const Config* config) {
|
|||||||
config->type == FEATURE_XMP) {
|
config->type == FEATURE_XMP) {
|
||||||
err = WebPMuxDeleteChunk(mux, kFourccList[config->type]);
|
err = WebPMuxDeleteChunk(mux, kFourccList[config->type]);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n",
|
ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n", ErrorString(err),
|
||||||
ErrorString(err), kDescriptions[config->type], Err2);
|
kDescriptions[config->type], Err2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
|
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
|
||||||
@@ -1234,7 +1244,7 @@ static int Process(const Config* config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err2:
|
Err2:
|
||||||
WebPMuxDelete(mux);
|
WebPMuxDelete(mux);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ WEBP_EXTERN int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
|
|||||||
// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any,
|
// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any,
|
||||||
// will be discarded. Returns 'false' in case of error, or if indexed[] contains
|
// will be discarded. Returns 'false' in case of error, or if indexed[] contains
|
||||||
// invalid indices.
|
// invalid indices.
|
||||||
WEBP_EXTERN int
|
WEBP_EXTERN int WebPImportColorMappedARGB(const uint8_t* indexed,
|
||||||
WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
|
int indexed_stride,
|
||||||
const uint32_t palette[], int palette_size,
|
const uint32_t palette[],
|
||||||
WebPPicture* pic);
|
int palette_size, WebPPicture* pic);
|
||||||
|
|
||||||
// Convert the ARGB content of 'pic' from associated to unassociated.
|
// Convert the ARGB content of 'pic' from associated to unassociated.
|
||||||
// 'pic' can be for instance the result of calling of some WebPPictureImportXXX
|
// 'pic' can be for instance the result of calling of some WebPPictureImportXXX
|
||||||
@@ -98,10 +98,12 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
|
|||||||
// currently supported.
|
// currently supported.
|
||||||
// width, height: width and height of the image in pixels
|
// width, height: width and height of the image in pixels
|
||||||
// Returns 0 on failure.
|
// Returns 0 on failure.
|
||||||
WEBP_EXTERN int SharpYuvEstimate420Risk(
|
WEBP_EXTERN int SharpYuvEstimate420Risk(const void* r_ptr, const void* g_ptr,
|
||||||
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
|
const void* b_ptr, int rgb_step,
|
||||||
int rgb_stride, int rgb_bit_depth, int width, int height,
|
int rgb_stride, int rgb_bit_depth,
|
||||||
const SharpYuvOptions* options, float* score);
|
int width, int height,
|
||||||
|
const SharpYuvOptions* options,
|
||||||
|
float* score);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
|
|||||||
reader = WebPGuessImageReader(data, data_size);
|
reader = WebPGuessImageReader(data, data_size);
|
||||||
ok = reader(data, data_size, pic, keep_alpha, NULL);
|
ok = reader(data, data_size, pic, keep_alpha, NULL);
|
||||||
|
|
||||||
End:
|
End:
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
||||||
(const W_CHAR*)filename);
|
(const W_CHAR*)filename);
|
||||||
@@ -57,8 +57,8 @@ static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
|
|||||||
return ok ? data_size : 0;
|
return ok ? data_size : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RescalePlane(uint8_t* plane, int width, int height,
|
static void RescalePlane(uint8_t* plane, int width, int height, int x_stride,
|
||||||
int x_stride, int y_stride, int max) {
|
int y_stride, int max) {
|
||||||
const uint32_t factor = (max > 0) ? (255u << 16) / max : 0;
|
const uint32_t factor = (max > 0) ? (255u << 16) / max : 0;
|
||||||
int x, y;
|
int x, y;
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
@@ -71,9 +71,9 @@ static void RescalePlane(uint8_t* plane, int width, int height,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the max absolute difference.
|
// Return the max absolute difference.
|
||||||
static int DiffScaleChannel(uint8_t* src1, int stride1,
|
static int DiffScaleChannel(uint8_t* src1, int stride1, const uint8_t* src2,
|
||||||
const uint8_t* src2, int stride2,
|
int stride2, int x_stride, int w, int h,
|
||||||
int x_stride, int w, int h, int do_scaling) {
|
int do_scaling) {
|
||||||
int x, y;
|
int x, y;
|
||||||
int max = 0;
|
int max = 0;
|
||||||
for (y = 0; y < h; ++y) {
|
for (y = 0; y < h; ++y) {
|
||||||
@@ -105,7 +105,7 @@ typedef struct {
|
|||||||
} DistoStats;
|
} DistoStats;
|
||||||
|
|
||||||
// hat-shaped filter. Sum of coefficients is equal to 16.
|
// hat-shaped filter. Sum of coefficients is equal to 16.
|
||||||
static const uint32_t kWeight[2 * SSIM_KERNEL + 1] = { 1, 2, 3, 4, 3, 2, 1 };
|
static const uint32_t kWeight[2 * SSIM_KERNEL + 1] = {1, 2, 3, 4, 3, 2, 1};
|
||||||
|
|
||||||
static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
||||||
const uint32_t N = stats->w;
|
const uint32_t N = stats->w;
|
||||||
@@ -133,9 +133,9 @@ static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
||||||
const uint8_t* src2, int stride2,
|
const uint8_t* src2, int stride2, int xo, int yo,
|
||||||
int xo, int yo, int W, int H) {
|
int W, int H) {
|
||||||
DistoStats stats = { 0, 0, 0, 0, 0, 0 };
|
DistoStats stats = {0, 0, 0, 0, 0, 0};
|
||||||
const int ymin = (yo - SSIM_KERNEL < 0) ? 0 : yo - SSIM_KERNEL;
|
const int ymin = (yo - SSIM_KERNEL < 0) ? 0 : yo - SSIM_KERNEL;
|
||||||
const int ymax = (yo + SSIM_KERNEL > H - 1) ? H - 1 : yo + SSIM_KERNEL;
|
const int ymax = (yo + SSIM_KERNEL > H - 1) ? H - 1 : yo + SSIM_KERNEL;
|
||||||
const int xmin = (xo - SSIM_KERNEL < 0) ? 0 : xo - SSIM_KERNEL;
|
const int xmin = (xo - SSIM_KERNEL < 0) ? 0 : xo - SSIM_KERNEL;
|
||||||
@@ -145,8 +145,8 @@ static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
|||||||
src2 += ymin * stride2;
|
src2 += ymin * stride2;
|
||||||
for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
|
for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
|
||||||
for (x = xmin; x <= xmax; ++x) {
|
for (x = xmin; x <= xmax; ++x) {
|
||||||
const uint32_t w = kWeight[SSIM_KERNEL + x - xo]
|
const uint32_t w =
|
||||||
* kWeight[SSIM_KERNEL + y - yo];
|
kWeight[SSIM_KERNEL + x - xo] * kWeight[SSIM_KERNEL + y - yo];
|
||||||
const uint32_t s1 = src1[x];
|
const uint32_t s1 = src1[x];
|
||||||
const uint32_t s2 = src2[x];
|
const uint32_t s2 = src2[x];
|
||||||
stats.w += w;
|
stats.w += w;
|
||||||
@@ -161,9 +161,9 @@ static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute SSIM-score map. Return -1 in case of error, max diff otherwise.
|
// Compute SSIM-score map. Return -1 in case of error, max diff otherwise.
|
||||||
static int SSIMScaleChannel(uint8_t* src1, int stride1,
|
static int SSIMScaleChannel(uint8_t* src1, int stride1, const uint8_t* src2,
|
||||||
const uint8_t* src2, int stride2,
|
int stride2, int x_stride, int w, int h,
|
||||||
int x_stride, int w, int h, int do_scaling) {
|
int do_scaling) {
|
||||||
int x, y;
|
int x, y;
|
||||||
int max = 0;
|
int max = 0;
|
||||||
uint8_t* const plane1 = (uint8_t*)malloc(2 * w * h * sizeof(*plane1));
|
uint8_t* const plane1 = (uint8_t*)malloc(2 * w * h * sizeof(*plane1));
|
||||||
@@ -297,8 +297,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
fprintf(stderr, "Error while computing the distortion.\n");
|
fprintf(stderr, "Error while computing the distortion.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n",
|
printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n", (unsigned int)size1,
|
||||||
(unsigned int)size1,
|
|
||||||
disto[4], disto[0], disto[1], disto[2], disto[3],
|
disto[4], disto[0], disto[1], disto[2], disto[3],
|
||||||
8.f * size1 / pic1.width / pic1.height);
|
8.f * size1 / pic1.width / pic1.height);
|
||||||
|
|
||||||
@@ -306,7 +305,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
uint8_t* data = NULL;
|
uint8_t* data = NULL;
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
if (pic1.use_argb != pic2.use_argb) {
|
if (pic1.use_argb != pic2.use_argb) {
|
||||||
fprintf(stderr, "Pictures are not in the same argb format. "
|
fprintf(stderr,
|
||||||
|
"Pictures are not in the same argb format. "
|
||||||
"Can't save the difference map.\n");
|
"Can't save the difference map.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
@@ -314,13 +314,16 @@ int main(int argc, const char* argv[]) {
|
|||||||
int n;
|
int n;
|
||||||
fprintf(stderr, "max differences per channel: ");
|
fprintf(stderr, "max differences per channel: ");
|
||||||
for (n = 0; n < 3; ++n) { // skip the alpha channel
|
for (n = 0; n < 3; ++n) { // skip the alpha channel
|
||||||
const int range = (type == 1) ?
|
const int range =
|
||||||
SSIMScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
(type == 1)
|
||||||
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4,
|
? SSIMScaleChannel(
|
||||||
4, pic1.width, pic1.height, scale) :
|
(uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
||||||
DiffScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4, 4,
|
||||||
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4,
|
pic1.width, pic1.height, scale)
|
||||||
4, pic1.width, pic1.height, scale);
|
: DiffScaleChannel(
|
||||||
|
(uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
||||||
|
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4, 4,
|
||||||
|
pic1.width, pic1.height, scale);
|
||||||
if (range < 0) fprintf(stderr, "\nError computing diff map\n");
|
if (range < 0) fprintf(stderr, "\nError computing diff map\n");
|
||||||
fprintf(stderr, "[%d]", range);
|
fprintf(stderr, "[%d]", range);
|
||||||
}
|
}
|
||||||
@@ -331,10 +334,9 @@ int main(int argc, const char* argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
#if !defined(WEBP_REDUCE_CSP)
|
#if !defined(WEBP_REDUCE_CSP)
|
||||||
data_size = WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb,
|
data_size =
|
||||||
pic1.width, pic1.height,
|
WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb, pic1.width,
|
||||||
pic1.argb_stride * 4,
|
pic1.height, pic1.argb_stride * 4, &data);
|
||||||
&data);
|
|
||||||
if (data_size == 0) {
|
if (data_size == 0) {
|
||||||
fprintf(stderr, "Error during lossless encoding.\n");
|
fprintf(stderr, "Error during lossless encoding.\n");
|
||||||
goto End;
|
goto End;
|
||||||
@@ -346,14 +348,15 @@ int main(int argc, const char* argv[]) {
|
|||||||
#else
|
#else
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
fprintf(stderr, "Cannot save the difference map. Please recompile "
|
fprintf(stderr,
|
||||||
|
"Cannot save the difference map. Please recompile "
|
||||||
"without the WEBP_REDUCE_CSP flag.\n");
|
"without the WEBP_REDUCE_CSP flag.\n");
|
||||||
goto End;
|
goto End;
|
||||||
#endif // WEBP_REDUCE_CSP
|
#endif // WEBP_REDUCE_CSP
|
||||||
}
|
}
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
WebPPictureFree(&pic1);
|
WebPPictureFree(&pic1);
|
||||||
WebPPictureFree(&pic2);
|
WebPPictureFree(&pic2);
|
||||||
FREE_WARGV_AND_RETURN(ret);
|
FREE_WARGV_AND_RETURN(ret);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ int VP8EstimateQuality(const uint8_t* const data, size_t size) {
|
|||||||
const int update_map = GET_BIT(1);
|
const int update_map = GET_BIT(1);
|
||||||
if (GET_BIT(1)) { // update data
|
if (GET_BIT(1)) { // update data
|
||||||
const int absolute_delta = GET_BIT(1);
|
const int absolute_delta = GET_BIT(1);
|
||||||
int q[4] = { 0, 0, 0, 0 };
|
int q[4] = {0, 0, 0, 0};
|
||||||
for (s = 0; s < 4; ++s) {
|
for (s = 0; s < 4; ++s) {
|
||||||
if (GET_BIT(1)) {
|
if (GET_BIT(1)) {
|
||||||
q[s] = GET_BIT(7);
|
q[s] = GET_BIT(7);
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_SDL)
|
#if defined(WEBP_HAVE_SDL)
|
||||||
|
|
||||||
#include "webp_to_sdl.h"
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "imageio/imageio_util.h"
|
|
||||||
#include "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
|
#include "imageio/imageio_util.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "webp_to_sdl.h"
|
||||||
|
|
||||||
#if defined(WEBP_HAVE_JUST_SDL_H)
|
#if defined(WEBP_HAVE_JUST_SDL_H)
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
@@ -41,11 +41,15 @@ static void ProcessEvents(void) {
|
|||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
switch (event.key.keysym.sym) {
|
switch (event.key.keysym.sym) {
|
||||||
case SDLK_q: done = 1; break;
|
case SDLK_q:
|
||||||
default: break;
|
done = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +97,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "extras/extras.h"
|
#include "extras/extras.h"
|
||||||
#include "imageio/imageio_util.h"
|
#include "imageio/imageio_util.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
|||||||
@@ -17,11 +17,10 @@
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_SDL)
|
#if defined(WEBP_HAVE_SDL)
|
||||||
|
|
||||||
#include "webp_to_sdl.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "src/webp/decode.h"
|
#include "src/webp/decode.h"
|
||||||
|
#include "webp_to_sdl.h"
|
||||||
|
|
||||||
#if defined(WEBP_HAVE_JUST_SDL_H)
|
#if defined(WEBP_HAVE_JUST_SDL_H)
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
@@ -67,11 +66,11 @@ int WebPToSDL(const char* data, unsigned int data_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
output = WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width,
|
output =
|
||||||
&height);
|
WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width, &height);
|
||||||
#else
|
#else
|
||||||
output = WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width,
|
output =
|
||||||
&height);
|
WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width, &height);
|
||||||
#endif
|
#endif
|
||||||
if (output == NULL) {
|
if (output == NULL) {
|
||||||
fprintf(stderr, "Error decoding image (%d)\n", status);
|
fprintf(stderr, "Error decoding image (%d)\n", status);
|
||||||
@@ -84,7 +83,7 @@ int WebPToSDL(const char* data, unsigned int data_size) {
|
|||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
// We should call SDL_DestroyWindow(window) but that makes .js fail.
|
// We should call SDL_DestroyWindow(window) but that makes .js fail.
|
||||||
SDL_DestroyRenderer(renderer);
|
SDL_DestroyRenderer(renderer);
|
||||||
SDL_DestroyTexture(texture);
|
SDL_DestroyTexture(texture);
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
//
|
//
|
||||||
// Generic image-type guessing.
|
// Generic image-type guessing.
|
||||||
|
|
||||||
|
#include "./image_dec.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "./image_dec.h"
|
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
@@ -62,8 +63,8 @@ WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int FailReader(const uint8_t* const data, size_t data_size,
|
static int FailReader(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
int keep_alpha, struct Metadata* const metadata) {
|
struct Metadata* const metadata) {
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
@@ -74,12 +75,18 @@ static int FailReader(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
WebPImageReader WebPGetImageReader(WebPInputFileFormat format) {
|
WebPImageReader WebPGetImageReader(WebPInputFileFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case WEBP_PNG_FORMAT: return ReadPNG;
|
case WEBP_PNG_FORMAT:
|
||||||
case WEBP_JPEG_FORMAT: return ReadJPEG;
|
return ReadPNG;
|
||||||
case WEBP_TIFF_FORMAT: return ReadTIFF;
|
case WEBP_JPEG_FORMAT:
|
||||||
case WEBP_WEBP_FORMAT: return ReadWebP;
|
return ReadJPEG;
|
||||||
case WEBP_PNM_FORMAT: return ReadPNM;
|
case WEBP_TIFF_FORMAT:
|
||||||
default: return FailReader;
|
return ReadTIFF;
|
||||||
|
case WEBP_WEBP_FORMAT:
|
||||||
|
return ReadWebP;
|
||||||
|
case WEBP_PNM_FORMAT:
|
||||||
|
return ReadPNM;
|
||||||
|
default:
|
||||||
|
return FailReader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "./metadata.h"
|
|
||||||
#include "./jpegdec.h"
|
#include "./jpegdec.h"
|
||||||
|
#include "./metadata.h"
|
||||||
#include "./pngdec.h"
|
#include "./pngdec.h"
|
||||||
#include "./pnmdec.h"
|
#include "./pnmdec.h"
|
||||||
#include "./tiffdec.h"
|
#include "./tiffdec.h"
|
||||||
@@ -53,8 +53,8 @@ WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
|
|||||||
|
|
||||||
// Signature for common image-reading functions (ReadPNG, ReadJPEG, ...)
|
// Signature for common image-reading functions (ReadPNG, ReadJPEG, ...)
|
||||||
typedef int (*WebPImageReader)(const uint8_t* const data, size_t data_size,
|
typedef int (*WebPImageReader)(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
int keep_alpha, struct Metadata* const metadata);
|
struct Metadata* const metadata);
|
||||||
|
|
||||||
// Return the reader associated to a given file format.
|
// Return the reader associated to a given file format.
|
||||||
WebPImageReader WebPGetImageReader(WebPInputFileFormat format);
|
WebPImageReader WebPGetImageReader(WebPInputFileFormat format);
|
||||||
|
|||||||
@@ -26,13 +26,14 @@
|
|||||||
#endif
|
#endif
|
||||||
#define CINTERFACE
|
#define CINTERFACE
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
#define _WIN32_IE \
|
||||||
|
0x500 // Workaround bug in shlwapi.h when compiling C++
|
||||||
// code with COBJMACROS.
|
// code with COBJMACROS.
|
||||||
#include <ole2.h> // CreateStreamOnHGlobal()
|
#include <ole2.h> // CreateStreamOnHGlobal()
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <windows.h>
|
|
||||||
#include <wincodec.h>
|
#include <wincodec.h>
|
||||||
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
@@ -59,8 +60,8 @@
|
|||||||
#define MAKE_REFGUID(x) &(x)
|
#define MAKE_REFGUID(x) &(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static HRESULT CreateOutputStream(const char* out_file_name,
|
static HRESULT CreateOutputStream(const char* out_file_name, int write_to_mem,
|
||||||
int write_to_mem, IStream** stream) {
|
IStream** stream) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (write_to_mem) {
|
if (write_to_mem) {
|
||||||
// Output to a memory buffer. This is freed when 'stream' is released.
|
// Output to a memory buffer. This is freed when 'stream' is released.
|
||||||
@@ -77,24 +78,22 @@ static HRESULT CreateOutputStream(const char* out_file_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
||||||
REFGUID container_guid,
|
REFGUID container_guid, uint8_t* rgb, int stride,
|
||||||
uint8_t* rgb, int stride,
|
|
||||||
uint32_t width, uint32_t height, int has_alpha) {
|
uint32_t width, uint32_t height, int has_alpha) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
IWICImagingFactory* factory = NULL;
|
IWICImagingFactory* factory = NULL;
|
||||||
IWICBitmapFrameEncode* frame = NULL;
|
IWICBitmapFrameEncode* frame = NULL;
|
||||||
IWICBitmapEncoder* encoder = NULL;
|
IWICBitmapEncoder* encoder = NULL;
|
||||||
IStream* stream = NULL;
|
IStream* stream = NULL;
|
||||||
WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA
|
WICPixelFormatGUID pixel_format =
|
||||||
: GUID_WICPixelFormat24bppBGR;
|
has_alpha ? GUID_WICPixelFormat32bppBGRA : GUID_WICPixelFormat24bppBGR;
|
||||||
|
|
||||||
if (out_file_name == NULL || rgb == NULL) return E_INVALIDARG;
|
if (out_file_name == NULL || rgb == NULL) return E_INVALIDARG;
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
IFS(CoInitialize(NULL));
|
||||||
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
IFS(CoCreateInstance(
|
||||||
CLSCTX_INPROC_SERVER,
|
MAKE_REFGUID(CLSID_WICImagingFactory), NULL, CLSCTX_INPROC_SERVER,
|
||||||
MAKE_REFGUID(IID_IWICImagingFactory),
|
MAKE_REFGUID(IID_IWICImagingFactory), (LPVOID*)&factory));
|
||||||
(LPVOID*)&factory));
|
|
||||||
if (hr == REGDB_E_CLASSNOTREG) {
|
if (hr == REGDB_E_CLASSNOTREG) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Couldn't access Windows Imaging Component (are you running "
|
"Couldn't access Windows Imaging Component (are you running "
|
||||||
@@ -104,14 +103,13 @@ static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
|||||||
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
|
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
|
||||||
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
|
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
|
||||||
&encoder));
|
&encoder));
|
||||||
IFS(IWICBitmapEncoder_Initialize(encoder, stream,
|
IFS(IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache));
|
||||||
WICBitmapEncoderNoCache));
|
|
||||||
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
|
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
|
||||||
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
|
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
|
||||||
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
|
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
|
||||||
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
|
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
|
||||||
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride,
|
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride, height * stride,
|
||||||
height * stride, rgb));
|
rgb));
|
||||||
IFS(IWICBitmapFrameEncode_Commit(frame));
|
IFS(IWICBitmapFrameEncode_Commit(frame));
|
||||||
IFS(IWICBitmapEncoder_Commit(encoder));
|
IFS(IWICBitmapEncoder_Commit(encoder));
|
||||||
|
|
||||||
@@ -153,8 +151,8 @@ int WebPWritePNG(const char* out_file_name, int use_stdout,
|
|||||||
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||||
|
|
||||||
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
|
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
|
||||||
MAKE_REFGUID(GUID_ContainerFormatPng),
|
MAKE_REFGUID(GUID_ContainerFormatPng), rgb,
|
||||||
rgb, stride, width, height, has_alpha));
|
stride, width, height, has_alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
||||||
@@ -169,8 +167,8 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
|
|
||||||
if (out_file == NULL || buffer == NULL) return 0;
|
if (out_file == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNGErrorFunction,
|
||||||
NULL, PNGErrorFunction, NULL);
|
NULL);
|
||||||
if (png == NULL) {
|
if (png == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -210,7 +208,8 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) {
|
int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
if (fout == NULL || buffer == NULL) return 0;
|
if (fout == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
fprintf(stderr, "PNG support not compiled. Please install the libpng "
|
fprintf(stderr,
|
||||||
|
"PNG support not compiled. Please install the libpng "
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
|
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -235,8 +234,10 @@ static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer,
|
|||||||
if (row == NULL) return 0;
|
if (row == NULL) return 0;
|
||||||
|
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
fprintf(fout,
|
||||||
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
"P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
||||||
|
"TUPLTYPE RGB_ALPHA\nENDHDR\n",
|
||||||
|
width, height);
|
||||||
} else {
|
} else {
|
||||||
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
||||||
}
|
}
|
||||||
@@ -310,7 +311,7 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
int stride;
|
int stride;
|
||||||
uint32_t y;
|
uint32_t y;
|
||||||
uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size;
|
uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size;
|
||||||
uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 };
|
uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = {0};
|
||||||
|
|
||||||
if (fout == NULL || buffer == NULL) return 0;
|
if (fout == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
@@ -367,7 +368,7 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
}
|
}
|
||||||
// write padding zeroes
|
// write padding zeroes
|
||||||
if (bmp_stride != line_size) {
|
if (bmp_stride != line_size) {
|
||||||
const uint8_t zeroes[3] = { 0 };
|
const uint8_t zeroes[3] = {0};
|
||||||
if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) {
|
if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -404,24 +405,24 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
|
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
|
||||||
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
|
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
|
||||||
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
|
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
|
||||||
EXTRA_DATA_OFFSET + 0, 0, 0, 0,
|
EXTRA_DATA_OFFSET + 0, 0, 0, 0, 0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0,
|
||||||
0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none
|
0, // 46: Compression: none
|
||||||
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
|
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
|
||||||
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
|
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
|
||||||
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
|
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
|
||||||
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
|
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
|
||||||
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
|
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
|
||||||
bytes_per_px, 0, 0, 0,
|
bytes_per_px, 0, 0, 0, 0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD)
|
0, // 106: Rows per strip (TBD)
|
||||||
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
|
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
|
||||||
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
|
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
|
||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0, 0x1b, 0x01, 5, 0, 1, 0, 0,
|
||||||
0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution
|
0, // 142: Y-resolution
|
||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0, 0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0,
|
||||||
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
|
0, // 154: PlanarConfiguration
|
||||||
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
||||||
0x52, 0x01, 3, 0, 1, 0, 0, 0,
|
0x52, 0x01, 3, 0, 1, 0, 0, 0, assoc_alpha, 0, 0,
|
||||||
assoc_alpha, 0, 0, 0, // 178: ExtraSamples: rgbA/RGBA
|
0, // 178: ExtraSamples: rgbA/RGBA
|
||||||
0, 0, 0, 0, // 190: IFD terminator
|
0, 0, 0, 0, // 190: IFD terminator
|
||||||
// EXTRA_DATA_OFFSET:
|
// EXTRA_DATA_OFFSET:
|
||||||
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
||||||
@@ -517,8 +518,8 @@ int WebPWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
|
|
||||||
if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
|
if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
|
||||||
|
|
||||||
fprintf(fout, "P5\n%d %d\n255\n",
|
fprintf(fout, "P5\n%d %d\n255\n", (width + 1) & ~1,
|
||||||
(width + 1) & ~1, height + uv_height + a_height);
|
height + uv_height + a_height);
|
||||||
for (y = 0; ok && y < height; ++y) {
|
for (y = 0; ok && y < height; ++y) {
|
||||||
ok &= (fwrite(src_y, width, 1, fout) == 1);
|
ok &= (fwrite(src_y, width, 1, fout) == 1);
|
||||||
if (width & 1) fputc(0, fout); // padding byte
|
if (width & 1) fputc(0, fout); // padding byte
|
||||||
@@ -609,8 +610,7 @@ int WebPSaveImage(const WebPDecBuffer* const buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format == PNG ||
|
if (format == PNG || format == RGBA || format == BGRA || format == ARGB ||
|
||||||
format == RGBA || format == BGRA || format == ARGB ||
|
|
||||||
format == rgbA || format == bgrA || format == Argb) {
|
format == rgbA || format == bgrA || format == Argb) {
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
ok &= WebPWritePNG(out_file_name, use_stdout, buffer);
|
ok &= WebPWritePNG(out_file_name, use_stdout, buffer);
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "webp/types.h"
|
|
||||||
#include "webp/decode.h"
|
#include "webp/decode.h"
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -38,10 +38,19 @@ typedef enum {
|
|||||||
RAW_YUV,
|
RAW_YUV,
|
||||||
ALPHA_PLANE_ONLY, // this is for experimenting only
|
ALPHA_PLANE_ONLY, // this is for experimenting only
|
||||||
// forced colorspace output (for testing, mostly)
|
// forced colorspace output (for testing, mostly)
|
||||||
RGB, RGBA, BGR, BGRA, ARGB,
|
RGB,
|
||||||
RGBA_4444, RGB_565,
|
RGBA,
|
||||||
rgbA, bgrA, Argb, rgbA_4444,
|
BGR,
|
||||||
YUV, YUVA
|
BGRA,
|
||||||
|
ARGB,
|
||||||
|
RGBA_4444,
|
||||||
|
RGB_565,
|
||||||
|
rgbA,
|
||||||
|
bgrA,
|
||||||
|
Argb,
|
||||||
|
rgbA_4444,
|
||||||
|
YUV,
|
||||||
|
YUVA
|
||||||
} WebPOutputFileFormat;
|
} WebPOutputFileFormat;
|
||||||
|
|
||||||
// General all-purpose call.
|
// General all-purpose call.
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/types.h"
|
|
||||||
#include "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// File I/O
|
// File I/O
|
||||||
@@ -65,14 +65,14 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
|||||||
*data_size = size;
|
*data_size = size;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
free(input);
|
free(input);
|
||||||
fprintf(stderr, "Could not read from stdin\n");
|
fprintf(stderr, "Could not read from stdin\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImgIoUtilReadFile(const char* const file_name,
|
int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data,
|
||||||
const uint8_t** data, size_t* data_size) {
|
size_t* data_size) {
|
||||||
int ok;
|
int ok;
|
||||||
uint8_t* file_data;
|
uint8_t* file_data;
|
||||||
size_t file_size;
|
size_t file_size;
|
||||||
@@ -123,8 +123,8 @@ int ImgIoUtilReadFile(const char* const file_name,
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
int ImgIoUtilWriteFile(const char* const file_name,
|
int ImgIoUtilWriteFile(const char* const file_name, const uint8_t* data,
|
||||||
const uint8_t* data, size_t data_size) {
|
size_t data_size) {
|
||||||
int ok;
|
int ok;
|
||||||
FILE* out;
|
FILE* out;
|
||||||
const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-");
|
const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-");
|
||||||
@@ -145,8 +145,8 @@ int ImgIoUtilWriteFile(const char* const file_name,
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst,
|
||||||
uint8_t* dst, int dst_stride, int width, int height) {
|
int dst_stride, int width, int height) {
|
||||||
while (height-- > 0) {
|
while (height-- > 0) {
|
||||||
memcpy(dst, src, width * sizeof(*dst));
|
memcpy(dst, src, width * sizeof(*dst));
|
||||||
src += src_stride;
|
src += src_stride;
|
||||||
|
|||||||
@@ -36,22 +36,22 @@ FILE* ImgIoUtilSetBinaryMode(FILE* file);
|
|||||||
// to be used as a C-string.
|
// to be used as a C-string.
|
||||||
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
||||||
// the function ImgIoUtilReadFromStdin().
|
// the function ImgIoUtilReadFromStdin().
|
||||||
int ImgIoUtilReadFile(const char* const file_name,
|
int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data,
|
||||||
const uint8_t** data, size_t* data_size);
|
size_t* data_size);
|
||||||
|
|
||||||
// Same as ImgIoUtilReadFile(), but reads until EOF from stdin instead.
|
// Same as ImgIoUtilReadFile(), but reads until EOF from stdin instead.
|
||||||
int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
||||||
|
|
||||||
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
||||||
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
||||||
int ImgIoUtilWriteFile(const char* const file_name,
|
int ImgIoUtilWriteFile(const char* const file_name, const uint8_t* data,
|
||||||
const uint8_t* data, size_t data_size);
|
size_t data_size);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
||||||
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst,
|
||||||
uint8_t* dst, int dst_stride, int width, int height);
|
int dst_stride, int width, int height);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_JPEG
|
#ifdef WEBP_HAVE_JPEG
|
||||||
#include <jpeglib.h>
|
|
||||||
#include <jerror.h>
|
#include <jerror.h>
|
||||||
|
#include <jpeglib.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
// Metadata processing
|
// Metadata processing
|
||||||
|
|
||||||
#ifndef JPEG_APP1
|
#ifndef JPEG_APP1
|
||||||
# define JPEG_APP1 (JPEG_APP0 + 1)
|
#define JPEG_APP1 (JPEG_APP0 + 1)
|
||||||
#endif
|
#endif
|
||||||
#ifndef JPEG_APP2
|
#ifndef JPEG_APP2
|
||||||
# define JPEG_APP2 (JPEG_APP0 + 2)
|
#define JPEG_APP2 (JPEG_APP0 + 2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -74,8 +74,7 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
|
|
||||||
memset(iccp_segments, 0, sizeof(iccp_segments));
|
memset(iccp_segments, 0, sizeof(iccp_segments));
|
||||||
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
|
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||||
if (marker->marker == JPEG_APP2 &&
|
if (marker->marker == JPEG_APP2 && marker->data_length > kICCPSkipLength &&
|
||||||
marker->data_length > kICCPSkipLength &&
|
|
||||||
!memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) {
|
!memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) {
|
||||||
// ICC_PROFILE\0<seq><count>; 'seq' starts at 1.
|
// ICC_PROFILE\0<seq><count>; 'seq' starts at 1.
|
||||||
const int seq = marker->data[kICCPSignatureLength];
|
const int seq = marker->data[kICCPSignatureLength];
|
||||||
@@ -84,7 +83,8 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
ICCPSegment* segment;
|
ICCPSegment* segment;
|
||||||
|
|
||||||
if (segment_size == 0 || count == 0 || seq == 0) {
|
if (segment_size == 0 || count == 0 || seq == 0) {
|
||||||
fprintf(stderr, "[ICCP] size (%d) / count (%d) / sequence number (%d)"
|
fprintf(stderr,
|
||||||
|
"[ICCP] size (%d) / count (%d) / sequence number (%d)"
|
||||||
" cannot be 0!\n",
|
" cannot be 0!\n",
|
||||||
(int)segment_size, seq, count);
|
(int)segment_size, seq, count);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -100,7 +100,7 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
|
|
||||||
segment = iccp_segments + seq - 1;
|
segment = iccp_segments + seq - 1;
|
||||||
if (segment->data_length != 0) {
|
if (segment->data_length != 0) {
|
||||||
fprintf(stderr, "[ICCP] Duplicate segment number (%d)!\n" , seq);
|
fprintf(stderr, "[ICCP] Duplicate segment number (%d)!\n", seq);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +138,8 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
int i;
|
int i;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (i = 0; i < seq_max; ++i) {
|
for (i = 0; i < seq_max; ++i) {
|
||||||
memcpy(iccp->bytes + offset,
|
memcpy(iccp->bytes + offset, iccp_segments[i].data,
|
||||||
iccp_segments[i].data, iccp_segments[i].data_length);
|
iccp_segments[i].data_length);
|
||||||
offset += iccp_segments[i].data_length;
|
offset += iccp_segments[i].data_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,11 +157,11 @@ static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo,
|
|||||||
size_t storage_offset;
|
size_t storage_offset;
|
||||||
} kJPEGMetadataMap[] = {
|
} kJPEGMetadataMap[] = {
|
||||||
// Exif 2.2 Section 4.7.2 Interoperability Structure of APP1 ...
|
// Exif 2.2 Section 4.7.2 Interoperability Structure of APP1 ...
|
||||||
{ JPEG_APP1, "Exif\0", 6, METADATA_OFFSET(exif) },
|
{JPEG_APP1, "Exif\0", 6, METADATA_OFFSET(exif)},
|
||||||
// XMP Specification Part 3 Section 3 Embedding XMP Metadata ... #JPEG
|
// XMP Specification Part 3 Section 3 Embedding XMP Metadata ... #JPEG
|
||||||
// TODO(jzern) Add support for 'ExtendedXMP'
|
// TODO(jzern) Add support for 'ExtendedXMP'
|
||||||
{ JPEG_APP1, "http://ns.adobe.com/xap/1.0/", 29, METADATA_OFFSET(xmp) },
|
{JPEG_APP1, "http://ns.adobe.com/xap/1.0/", 29, METADATA_OFFSET(xmp)},
|
||||||
{ 0, NULL, 0, 0 },
|
{0, NULL, 0, 0},
|
||||||
};
|
};
|
||||||
jpeg_saved_marker_ptr marker;
|
jpeg_saved_marker_ptr marker;
|
||||||
// Treat ICC profiles separately as they may be segmented and out of order.
|
// Treat ICC profiles separately as they may be segmented and out of order.
|
||||||
@@ -179,8 +179,8 @@ static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo,
|
|||||||
kJPEGMetadataMap[i].storage_offset);
|
kJPEGMetadataMap[i].storage_offset);
|
||||||
|
|
||||||
if (payload->bytes == NULL) {
|
if (payload->bytes == NULL) {
|
||||||
const char* marker_data = (const char*)marker->data +
|
const char* marker_data =
|
||||||
kJPEGMetadataMap[i].signature_length;
|
(const char*)marker->data + kJPEGMetadataMap[i].signature_length;
|
||||||
const size_t marker_data_length =
|
const size_t marker_data_length =
|
||||||
marker->data_length - kJPEGMetadataMap[i].signature_length;
|
marker->data_length - kJPEGMetadataMap[i].signature_length;
|
||||||
if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0;
|
if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0;
|
||||||
@@ -250,9 +250,7 @@ static void ContextSkip(j_decompress_ptr cinfo, long jump_size) {
|
|||||||
ctx->pub.next_input_byte += jump;
|
ctx->pub.next_input_byte += jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ContextTerm(j_decompress_ptr cinfo) {
|
static void ContextTerm(j_decompress_ptr cinfo) { (void)cinfo; }
|
||||||
(void)cinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
||||||
JPEGReadContext* const ctx) {
|
JPEGReadContext* const ctx) {
|
||||||
@@ -267,8 +265,7 @@ static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha,
|
WebPPicture* const pic, int keep_alpha, Metadata* const metadata) {
|
||||||
Metadata* const metadata) {
|
|
||||||
volatile int ok = 0;
|
volatile int ok = 0;
|
||||||
int width, height;
|
int width, height;
|
||||||
int64_t stride;
|
int64_t stride;
|
||||||
@@ -353,7 +350,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
MetadataFree(metadata); // In case the caller forgets to free it on error.
|
MetadataFree(metadata); // In case the caller forgets to free it on error.
|
||||||
}
|
}
|
||||||
|
|
||||||
End:
|
End:
|
||||||
free(rgb);
|
free(rgb);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -366,7 +363,8 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
|
fprintf(stderr,
|
||||||
|
"JPEG support not compiled. Please install the libjpeg "
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2
|
#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2
|
||||||
#endif
|
#endif
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
#include <setjmp.h> // note: this must be included *after* png.h
|
#include <setjmp.h> // note: this must be included *after* png.h
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -33,15 +32,14 @@
|
|||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
|
||||||
#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR)
|
#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR)
|
||||||
#define LOCAL_PNG_PREREQ(maj, min) \
|
#define LOCAL_PNG_PREREQ(maj, min) (LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
|
||||||
(LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
|
|
||||||
|
|
||||||
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
||||||
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
|
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
|
||||||
longjmp(png_jmpbuf(png), 1);
|
longjmp(png_jmpbuf(png), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LOCAL_PNG_PREREQ(1,4)
|
#if LOCAL_PNG_PREREQ(1, 4)
|
||||||
typedef png_alloc_size_t LocalPngAllocSize;
|
typedef png_alloc_size_t LocalPngAllocSize;
|
||||||
#else
|
#else
|
||||||
typedef png_size_t LocalPngAllocSize;
|
typedef png_size_t LocalPngAllocSize;
|
||||||
@@ -113,7 +111,8 @@ static int ProcessRawProfile(const char* profile, size_t profile_len,
|
|||||||
}
|
}
|
||||||
++src;
|
++src;
|
||||||
// skip the profile name and extract the length.
|
// skip the profile name and extract the length.
|
||||||
while (*src != '\0' && *src++ != '\n') {}
|
while (*src != '\0' && *src++ != '\n') {
|
||||||
|
}
|
||||||
expected_length = (int)strtol(src, &end, 10);
|
expected_length = (int)strtol(src, &end, 10);
|
||||||
if (*end != '\n') {
|
if (*end != '\n') {
|
||||||
fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
|
fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
|
||||||
@@ -137,23 +136,22 @@ static const struct {
|
|||||||
} kPNGMetadataMap[] = {
|
} kPNGMetadataMap[] = {
|
||||||
// https://exiftool.org/TagNames/PNG.html#TextualData
|
// https://exiftool.org/TagNames/PNG.html#TextualData
|
||||||
// See also: ExifTool on CPAN.
|
// See also: ExifTool on CPAN.
|
||||||
{ "Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif) },
|
{"Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif)},
|
||||||
{ "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) },
|
{"Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp)},
|
||||||
// Exiftool puts exif data in APP1 chunk, too.
|
// Exiftool puts exif data in APP1 chunk, too.
|
||||||
{ "Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif) },
|
{"Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif)},
|
||||||
// ImageMagick uses lowercase app1.
|
// ImageMagick uses lowercase app1.
|
||||||
{ "Raw profile type app1", ProcessRawProfile, METADATA_OFFSET(exif) },
|
{"Raw profile type app1", ProcessRawProfile, METADATA_OFFSET(exif)},
|
||||||
// XMP Specification Part 3, Section 3 #PNG
|
// XMP Specification Part 3, Section 3 #PNG
|
||||||
{ "XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp) },
|
{"XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp)},
|
||||||
{ NULL, NULL, 0 },
|
{NULL, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Looks for metadata at both the beginning and end of the PNG file, giving
|
// Looks for metadata at both the beginning and end of the PNG file, giving
|
||||||
// preference to the head.
|
// preference to the head.
|
||||||
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
|
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
|
||||||
// all cases.
|
// all cases.
|
||||||
static int ExtractMetadataFromPNG(png_structp png,
|
static int ExtractMetadataFromPNG(png_structp png, png_infop const head_info,
|
||||||
png_infop const head_info,
|
|
||||||
png_infop const end_info,
|
png_infop const end_info,
|
||||||
Metadata* const metadata) {
|
Metadata* const metadata) {
|
||||||
int p;
|
int p;
|
||||||
@@ -215,15 +213,15 @@ static int ExtractMetadataFromPNG(png_structp png,
|
|||||||
{
|
{
|
||||||
png_charp name;
|
png_charp name;
|
||||||
int comp_type;
|
int comp_type;
|
||||||
#if LOCAL_PNG_PREREQ(1,5)
|
#if LOCAL_PNG_PREREQ(1, 5)
|
||||||
png_bytep profile;
|
png_bytep profile;
|
||||||
#else
|
#else
|
||||||
png_charp profile;
|
png_charp profile;
|
||||||
#endif
|
#endif
|
||||||
png_uint_32 len;
|
png_uint_32 len;
|
||||||
|
|
||||||
if (png_get_iCCP(png, info,
|
if (png_get_iCCP(png, info, &name, &comp_type, &profile, &len) ==
|
||||||
&name, &comp_type, &profile, &len) == PNG_INFO_iCCP) {
|
PNG_INFO_iCCP) {
|
||||||
if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0;
|
if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,12 +246,12 @@ static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadPNG(const uint8_t* const data, size_t data_size,
|
int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
int keep_alpha, struct Metadata* const metadata) {
|
struct Metadata* const metadata) {
|
||||||
volatile png_structp png = NULL;
|
volatile png_structp png = NULL;
|
||||||
volatile png_infop info = NULL;
|
volatile png_infop info = NULL;
|
||||||
volatile png_infop end_info = NULL;
|
volatile png_infop end_info = NULL;
|
||||||
PNGReadContext context = { NULL, 0, 0 };
|
PNGReadContext context = {NULL, 0, 0};
|
||||||
int color_type, bit_depth, interlaced;
|
int color_type, bit_depth, interlaced;
|
||||||
int num_channels;
|
int num_channels;
|
||||||
int num_passes;
|
int num_passes;
|
||||||
@@ -268,8 +266,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
context.data = data;
|
context.data = data;
|
||||||
context.data_size = data_size;
|
context.data_size = data_size;
|
||||||
|
|
||||||
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
|
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL,
|
||||||
NULL, MallocFunc, FreeFunc);
|
MallocFunc, FreeFunc);
|
||||||
if (png == NULL) goto End;
|
if (png == NULL) goto End;
|
||||||
|
|
||||||
png_set_error_fn(png, 0, error_function, NULL);
|
png_set_error_fn(png, 0, error_function, NULL);
|
||||||
@@ -279,8 +277,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LOCAL_PNG_PREREQ(1,5) || \
|
#if LOCAL_PNG_PREREQ(1, 5) || \
|
||||||
(LOCAL_PNG_PREREQ(1,4) && PNG_LIBPNG_VER_RELEASE >= 1)
|
(LOCAL_PNG_PREREQ(1, 4) && PNG_LIBPNG_VER_RELEASE >= 1)
|
||||||
// If it looks like the bitstream is going to need more memory than libpng's
|
// If it looks like the bitstream is going to need more memory than libpng's
|
||||||
// internal limit (default: 8M), try to (reasonably) raise it.
|
// internal limit (default: 8M), try to (reasonably) raise it.
|
||||||
if (data_size > png_get_chunk_malloc_max(png) && data_size < (1u << 24)) {
|
if (data_size > png_get_chunk_malloc_max(png) && data_size < (1u << 24)) {
|
||||||
@@ -295,9 +293,9 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
png_set_read_fn(png, &context, ReadFunc);
|
png_set_read_fn(png, &context, ReadFunc);
|
||||||
png_read_info(png, info);
|
png_read_info(png, info);
|
||||||
if (!png_get_IHDR(png, info,
|
if (!png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type,
|
||||||
&width, &height, &bit_depth, &color_type, &interlaced,
|
&interlaced, NULL, NULL))
|
||||||
NULL, NULL)) goto Error;
|
goto Error;
|
||||||
|
|
||||||
png_set_strip_16(png);
|
png_set_strip_16(png);
|
||||||
png_set_packing(png);
|
png_set_packing(png);
|
||||||
@@ -368,24 +366,25 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
End:
|
End:
|
||||||
if (png != NULL) {
|
if (png != NULL) {
|
||||||
png_destroy_read_struct((png_structpp)&png,
|
png_destroy_read_struct((png_structpp)&png, (png_infopp)&info,
|
||||||
(png_infopp)&info, (png_infopp)&end_info);
|
(png_infopp)&end_info);
|
||||||
}
|
}
|
||||||
free(rgb);
|
free(rgb);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
#else // !WEBP_HAVE_PNG
|
#else // !WEBP_HAVE_PNG
|
||||||
int ReadPNG(const uint8_t* const data, size_t data_size,
|
int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
int keep_alpha, struct Metadata* const metadata) {
|
struct Metadata* const metadata) {
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr, "PNG support not compiled. Please install the libpng "
|
fprintf(stderr,
|
||||||
|
"PNG support not compiled. Please install the libpng "
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ struct WebPPicture;
|
|||||||
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int ReadPNG(const uint8_t* const data, size_t data_size,
|
int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
int keep_alpha, struct Metadata* const metadata);
|
struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ static size_t ReadLine(const uint8_t* const data, size_t off, size_t data_size,
|
|||||||
char out[MAX_LINE_SIZE + 1], size_t* const out_size) {
|
char out[MAX_LINE_SIZE + 1], size_t* const out_size) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
*out_size = 0;
|
*out_size = 0;
|
||||||
redo:
|
redo:
|
||||||
for (i = 0; i < MAX_LINE_SIZE && off < data_size; ++i) {
|
for (i = 0; i < MAX_LINE_SIZE && off < data_size; ++i) {
|
||||||
out[i] = data[off++];
|
out[i] = data[off++];
|
||||||
if (out[i] == '\n') break;
|
if (out[i] == '\n') break;
|
||||||
@@ -173,9 +173,8 @@ static size_t ReadHeader(PNMInfo* const info) {
|
|||||||
info->depth = (info->type == 5) ? 1 : 3;
|
info->depth = (info->type == 5) ? 1 : 3;
|
||||||
}
|
}
|
||||||
// perform some basic numerical validation
|
// perform some basic numerical validation
|
||||||
if (info->width <= 0 || info->height <= 0 ||
|
if (info->width <= 0 || info->height <= 0 || info->type <= 0 ||
|
||||||
info->type <= 0 || info->type >= 9 ||
|
info->type >= 9 || info->depth <= 0 || info->depth > 4 ||
|
||||||
info->depth <= 0 || info->depth > 4 ||
|
|
||||||
info->max_value <= 0 || info->max_value >= 65536) {
|
info->max_value <= 0 || info->max_value >= 65536) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -183,13 +182,12 @@ static size_t ReadHeader(PNMInfo* const info) {
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadPNM(const uint8_t* const data, size_t data_size,
|
int ReadPNM(const uint8_t* const data, size_t data_size, WebPPicture* const pic,
|
||||||
WebPPicture* const pic, int keep_alpha,
|
int keep_alpha, struct Metadata* const metadata) {
|
||||||
struct Metadata* const metadata) {
|
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
uint64_t stride, pixel_bytes, sample_size, depth;
|
uint64_t stride, pixel_bytes, sample_size, depth;
|
||||||
uint8_t* rgb = NULL, *tmp_rgb;
|
uint8_t *rgb = NULL, *tmp_rgb;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
PNMInfo info;
|
PNMInfo info;
|
||||||
|
|
||||||
@@ -209,8 +207,8 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
|
|||||||
// Some basic validations.
|
// Some basic validations.
|
||||||
if (pic == NULL) goto End;
|
if (pic == NULL) goto End;
|
||||||
if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) {
|
if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) {
|
||||||
fprintf(stderr, "Invalid %dx%d dimension for PNM\n",
|
fprintf(stderr, "Invalid %dx%d dimension for PNM\n", info.width,
|
||||||
info.width, info.height);
|
info.height);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,8 +256,8 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
|
|||||||
const uint32_t round = info.max_value / 2;
|
const uint32_t round = info.max_value / 2;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (i = 0; i < info.width * info.depth; ++i) {
|
for (i = 0; i < info.width * info.depth; ++i) {
|
||||||
uint32_t v = (sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1]
|
uint32_t v =
|
||||||
: in[i];
|
(sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1] : in[i];
|
||||||
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
|
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
|
||||||
if (v > 255u) v = 255u;
|
if (v > 255u) v = 255u;
|
||||||
if (info.depth > 2) {
|
if (info.depth > 2) {
|
||||||
@@ -291,7 +289,7 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
|
|||||||
if (!ok) goto End;
|
if (!ok) goto End;
|
||||||
|
|
||||||
ok = 1;
|
ok = 1;
|
||||||
End:
|
End:
|
||||||
free((void*)rgb);
|
free((void*)rgb);
|
||||||
|
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ static const struct {
|
|||||||
ttag_t tag;
|
ttag_t tag;
|
||||||
size_t storage_offset;
|
size_t storage_offset;
|
||||||
} kTIFFMetadataMap[] = {
|
} kTIFFMetadataMap[] = {
|
||||||
{ TIFFTAG_ICCPROFILE, METADATA_OFFSET(iccp) },
|
{TIFFTAG_ICCPROFILE, METADATA_OFFSET(iccp)},
|
||||||
{ TIFFTAG_XMLPACKET, METADATA_OFFSET(xmp) },
|
{TIFFTAG_XMLPACKET, METADATA_OFFSET(xmp)},
|
||||||
{ 0, 0 },
|
{0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
|
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
|
||||||
@@ -128,9 +128,7 @@ static uint32_t Unmult(uint8_t x, uint32_t mult) {
|
|||||||
return (v > 255u) ? 255u : v;
|
return (v > 255u) ? 255u : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t GetScale(uint32_t a) {
|
static WEBP_INLINE uint32_t GetScale(uint32_t a) { return (255u << MFIX) / a; }
|
||||||
return (255u << MFIX) / a;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef MFIX
|
#undef MFIX
|
||||||
#undef HALF
|
#undef HALF
|
||||||
@@ -153,9 +151,8 @@ static void MultARGBRow(uint8_t* ptr, int width) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha,
|
WebPPicture* const pic, int keep_alpha, Metadata* const metadata) {
|
||||||
Metadata* const metadata) {
|
MyData my_data = {data, (toff_t)data_size, 0};
|
||||||
MyData my_data = { data, (toff_t)data_size, 0 };
|
|
||||||
TIFF* tif;
|
TIFF* tif;
|
||||||
uint32_t image_width, image_height, tile_width, tile_height;
|
uint32_t image_width, image_height, tile_width, tile_height;
|
||||||
uint64_t stride;
|
uint64_t stride;
|
||||||
@@ -171,8 +168,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tif = TIFFClientOpen("Memory", "r", &my_data,
|
tif = TIFFClientOpen("Memory", "r", &my_data, MyRead, MyRead, MySeek, MyClose,
|
||||||
MyRead, MyRead, MySeek, MyClose,
|
|
||||||
MySize, MyMapFile, MyUnmapFile);
|
MySize, MyMapFile, MyUnmapFile);
|
||||||
if (tif == NULL) {
|
if (tif == NULL) {
|
||||||
fprintf(stderr, "Error! Cannot parse TIFF file\n");
|
fprintf(stderr, "Error! Cannot parse TIFF file\n");
|
||||||
@@ -181,7 +177,8 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
dircount = TIFFNumberOfDirectories(tif);
|
dircount = TIFFNumberOfDirectories(tif);
|
||||||
if (dircount > 1) {
|
if (dircount > 1) {
|
||||||
fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n"
|
fprintf(stderr,
|
||||||
|
"Warning: multi-directory TIFF files are not supported.\n"
|
||||||
"Only the first will be used, %d will be ignored.\n",
|
"Only the first will be used, %d will be ignored.\n",
|
||||||
dircount - 1);
|
dircount - 1);
|
||||||
}
|
}
|
||||||
@@ -253,7 +250,8 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
tmp += stride;
|
tmp += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = keep_alpha
|
ok =
|
||||||
|
keep_alpha
|
||||||
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
|
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
|
||||||
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
|
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
|
||||||
}
|
}
|
||||||
@@ -272,7 +270,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End:
|
End:
|
||||||
TIFFClose(tif);
|
TIFFClose(tif);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -285,7 +283,8 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr, "TIFF support not compiled. Please install the libtiff "
|
fprintf(stderr,
|
||||||
|
"TIFF support not compiled. Please install the libtiff "
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,14 @@
|
|||||||
// WebP decoding
|
// WebP decoding
|
||||||
|
|
||||||
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
||||||
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
|
"OK",
|
||||||
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
|
"OUT_OF_MEMORY",
|
||||||
};
|
"INVALID_PARAM",
|
||||||
|
"BITSTREAM_ERROR",
|
||||||
|
"UNSUPPORTED_FEATURE",
|
||||||
|
"SUSPENDED",
|
||||||
|
"USER_ABORT",
|
||||||
|
"NOT_ENOUGH_DATA"};
|
||||||
|
|
||||||
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
||||||
if (config->input.has_animation) {
|
if (config->input.has_animation) {
|
||||||
@@ -53,8 +58,7 @@ void PrintWebPError(const char* const in_file, int status) {
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int LoadWebP(const char* const in_file,
|
int LoadWebP(const char* const in_file, const uint8_t** data, size_t* data_size,
|
||||||
const uint8_t** data, size_t* data_size,
|
|
||||||
WebPBitstreamFeatures* bitstream) {
|
WebPBitstreamFeatures* bitstream) {
|
||||||
VP8StatusCode status;
|
VP8StatusCode status;
|
||||||
WebPBitstreamFeatures local_features;
|
WebPBitstreamFeatures local_features;
|
||||||
@@ -84,8 +88,7 @@ VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size,
|
|||||||
return WebPDecode(data, data_size, config);
|
return WebPDecode(data, data_size, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8StatusCode DecodeWebPIncremental(
|
VP8StatusCode DecodeWebPIncremental(const uint8_t* const data, size_t data_size,
|
||||||
const uint8_t* const data, size_t data_size,
|
|
||||||
WebPDecoderConfig* const config) {
|
WebPDecoderConfig* const config) {
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||||
@@ -111,7 +114,7 @@ VP8StatusCode DecodeWebPIncremental(
|
|||||||
|
|
||||||
static int ExtractMetadata(const uint8_t* const data, size_t data_size,
|
static int ExtractMetadata(const uint8_t* const data, size_t data_size,
|
||||||
Metadata* const metadata) {
|
Metadata* const metadata) {
|
||||||
WebPData webp_data = { data, data_size };
|
WebPData webp_data = {data, data_size};
|
||||||
WebPDemuxer* const demux = WebPDemux(&webp_data);
|
WebPDemuxer* const demux = WebPDemux(&webp_data);
|
||||||
WebPChunkIterator chunk_iter;
|
WebPChunkIterator chunk_iter;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@@ -143,8 +146,7 @@ static int ExtractMetadata(const uint8_t* const data, size_t data_size,
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic,
|
WebPPicture* const pic, int keep_alpha, Metadata* const metadata) {
|
||||||
int keep_alpha, Metadata* const metadata) {
|
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
WebPDecoderConfig config;
|
WebPDecoderConfig config;
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ void PrintWebPError(const char* const in_file, int status);
|
|||||||
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
|
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
|
||||||
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int LoadWebP(const char* const in_file,
|
int LoadWebP(const char* const in_file, const uint8_t** data, size_t* data_size,
|
||||||
const uint8_t** data, size_t* data_size,
|
|
||||||
WebPBitstreamFeatures* bitstream);
|
WebPBitstreamFeatures* bitstream);
|
||||||
|
|
||||||
// Decodes the WebP contained in 'data'.
|
// Decodes the WebP contained in 'data'.
|
||||||
@@ -48,8 +47,7 @@ VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size,
|
|||||||
WebPDecoderConfig* const config);
|
WebPDecoderConfig* const config);
|
||||||
|
|
||||||
// Same as DecodeWebP(), but using the incremental decoder.
|
// Same as DecodeWebP(), but using the incremental decoder.
|
||||||
VP8StatusCode DecodeWebPIncremental(
|
VP8StatusCode DecodeWebPIncremental(const uint8_t* const data, size_t data_size,
|
||||||
const uint8_t* const data, size_t data_size,
|
|
||||||
WebPDecoderConfig* const config);
|
WebPDecoderConfig* const config);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -60,8 +58,8 @@ VP8StatusCode DecodeWebPIncremental(
|
|||||||
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
int keep_alpha, struct Metadata* const metadata);
|
struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
108
imageio/wicdec.c
108
imageio/wicdec.c
@@ -25,13 +25,14 @@
|
|||||||
#endif
|
#endif
|
||||||
#define CINTERFACE
|
#define CINTERFACE
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
#define _WIN32_IE \
|
||||||
|
0x500 // Workaround bug in shlwapi.h when compiling C++
|
||||||
// code with COBJMACROS.
|
// code with COBJMACROS.
|
||||||
#include <ole2.h> // CreateStreamOnHGlobal()
|
#include <ole2.h> // CreateStreamOnHGlobal()
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <windows.h>
|
|
||||||
#include <wincodec.h>
|
#include <wincodec.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#include "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
#include "./imageio_util.h"
|
#include "./imageio_util.h"
|
||||||
@@ -48,8 +49,7 @@
|
|||||||
|
|
||||||
// modified version of DEFINE_GUID from guiddef.h.
|
// modified version of DEFINE_GUID from guiddef.h.
|
||||||
#define WEBP_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
#define WEBP_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
static const GUID name = \
|
static const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
|
||||||
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define MAKE_REFGUID(x) (x)
|
#define MAKE_REFGUID(x) (x)
|
||||||
@@ -66,23 +66,17 @@ typedef struct WICFormatImporter {
|
|||||||
// From Microsoft SDK 7.0a -- wincodec.h
|
// From Microsoft SDK 7.0a -- wincodec.h
|
||||||
// Create local copies for compatibility when building against earlier
|
// Create local copies for compatibility when building against earlier
|
||||||
// versions of the SDK.
|
// versions of the SDK.
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1,
|
||||||
0x6fddc324, 0x4e03, 0x4bfe,
|
0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c);
|
||||||
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c);
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1,
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_,
|
0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
|
||||||
0x6fddc324, 0x4e03, 0x4bfe,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_, 0x6fddc324, 0x4e03, 0x4bfe,
|
||||||
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
|
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_,
|
|
||||||
0x6fddc324, 0x4e03, 0x4bfe,
|
|
||||||
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
|
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_, 0xf5c7ad2d, 0x6a8d, 0x43dd,
|
||||||
0xf5c7ad2d, 0x6a8d, 0x43dd,
|
|
||||||
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
|
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppBGRA_,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppBGRA_, 0x1562ff7c, 0xd352, 0x46f9,
|
||||||
0x1562ff7c, 0xd352, 0x46f9,
|
|
||||||
0x97, 0x9e, 0x42, 0x97, 0x6b, 0x79, 0x22, 0x46);
|
0x97, 0x9e, 0x42, 0x97, 0x6b, 0x79, 0x22, 0x46);
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_, 0x6fddc324, 0x4e03, 0x4bfe,
|
||||||
0x6fddc324, 0x4e03, 0x4bfe,
|
|
||||||
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16);
|
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16);
|
||||||
|
|
||||||
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
||||||
@@ -147,8 +141,7 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
UINT num_color_contexts;
|
UINT num_color_contexts;
|
||||||
IFS(IWICBitmapFrameDecode_GetColorContexts(frame,
|
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, count, color_contexts,
|
||||||
count, color_contexts,
|
|
||||||
&num_color_contexts));
|
&num_color_contexts));
|
||||||
assert(FAILED(hr) || num_color_contexts <= count);
|
assert(FAILED(hr) || num_color_contexts <= count);
|
||||||
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
||||||
@@ -156,8 +149,8 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
IFS(IWICColorContext_GetType(color_contexts[i], &type));
|
IFS(IWICColorContext_GetType(color_contexts[i], &type));
|
||||||
if (SUCCEEDED(hr) && type == WICColorContextProfile) {
|
if (SUCCEEDED(hr) && type == WICColorContextProfile) {
|
||||||
UINT size;
|
UINT size;
|
||||||
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
|
IFS(IWICColorContext_GetProfileBytes(color_contexts[i], 0, NULL,
|
||||||
0, NULL, &size));
|
&size));
|
||||||
if (SUCCEEDED(hr) && size > 0) {
|
if (SUCCEEDED(hr) && size > 0) {
|
||||||
iccp->bytes = (uint8_t*)malloc(size);
|
iccp->bytes = (uint8_t*)malloc(size);
|
||||||
if (iccp->bytes == NULL) {
|
if (iccp->bytes == NULL) {
|
||||||
@@ -165,9 +158,8 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iccp->size = size;
|
iccp->size = size;
|
||||||
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
|
IFS(IWICColorContext_GetProfileBytes(
|
||||||
(UINT)iccp->size, iccp->bytes,
|
color_contexts[i], (UINT)iccp->size, iccp->bytes, &size));
|
||||||
&size));
|
|
||||||
if (SUCCEEDED(hr) && size != iccp->size) {
|
if (SUCCEEDED(hr) && size != iccp->size) {
|
||||||
fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n",
|
fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n",
|
||||||
size, (uint32_t)iccp->size);
|
size, (uint32_t)iccp->size);
|
||||||
@@ -209,8 +201,7 @@ static int HasPalette(GUID pixel_format) {
|
|||||||
|
|
||||||
static int HasAlpha(IWICImagingFactory* const factory,
|
static int HasAlpha(IWICImagingFactory* const factory,
|
||||||
IWICBitmapDecoder* const decoder,
|
IWICBitmapDecoder* const decoder,
|
||||||
IWICBitmapFrameDecode* const frame,
|
IWICBitmapFrameDecode* const frame, GUID pixel_format) {
|
||||||
GUID pixel_format) {
|
|
||||||
int has_alpha;
|
int has_alpha;
|
||||||
if (HasPalette(pixel_format)) {
|
if (HasPalette(pixel_format)) {
|
||||||
IWICPalette* frame_palette = NULL;
|
IWICPalette* frame_palette = NULL;
|
||||||
@@ -245,21 +236,20 @@ static int HasAlpha(IWICImagingFactory* const factory,
|
|||||||
return has_alpha;
|
return has_alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadPictureWithWIC(const char* const filename,
|
int ReadPictureWithWIC(const char* const filename, WebPPicture* const pic,
|
||||||
WebPPicture* const pic, int keep_alpha,
|
int keep_alpha, Metadata* const metadata) {
|
||||||
Metadata* const metadata) {
|
|
||||||
// From Microsoft SDK 6.0a -- ks.h
|
// From Microsoft SDK 6.0a -- ks.h
|
||||||
// Define a local copy to avoid link errors under mingw.
|
// Define a local copy to avoid link errors under mingw.
|
||||||
WEBP_DEFINE_GUID(GUID_NULL_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
WEBP_DEFINE_GUID(GUID_NULL_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
static const WICFormatImporter kAlphaFormatImporters[] = {
|
static const WICFormatImporter kAlphaFormatImporters[] = {
|
||||||
{ &GUID_WICPixelFormat32bppBGRA_, 4, WebPPictureImportBGRA },
|
{&GUID_WICPixelFormat32bppBGRA_, 4, WebPPictureImportBGRA},
|
||||||
{ &GUID_WICPixelFormat32bppRGBA_, 4, WebPPictureImportRGBA },
|
{&GUID_WICPixelFormat32bppRGBA_, 4, WebPPictureImportRGBA},
|
||||||
{ NULL, 0, NULL },
|
{NULL, 0, NULL},
|
||||||
};
|
};
|
||||||
static const WICFormatImporter kNonAlphaFormatImporters[] = {
|
static const WICFormatImporter kNonAlphaFormatImporters[] = {
|
||||||
{ &GUID_WICPixelFormat24bppBGR_, 3, WebPPictureImportBGR },
|
{&GUID_WICPixelFormat24bppBGR_, 3, WebPPictureImportBGR},
|
||||||
{ &GUID_WICPixelFormat24bppRGB_, 3, WebPPictureImportRGB },
|
{&GUID_WICPixelFormat24bppRGB_, 3, WebPPictureImportRGB},
|
||||||
{ NULL, 0, NULL },
|
{NULL, 0, NULL},
|
||||||
};
|
};
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
IWICBitmapFrameDecode* frame = NULL;
|
IWICBitmapFrameDecode* frame = NULL;
|
||||||
@@ -274,26 +264,20 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
const WICFormatImporter* importer = NULL;
|
const WICFormatImporter* importer = NULL;
|
||||||
GUID src_container_format = GUID_NULL_;
|
GUID src_container_format = GUID_NULL_;
|
||||||
// From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h
|
// From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h
|
||||||
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_,
|
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_, 0xe094b0e2, 0x67f2, 0x45b3, 0xb0,
|
||||||
0xe094b0e2, 0x67f2, 0x45b3,
|
0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
|
||||||
0xb0, 0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
|
|
||||||
static const GUID* kAlphaContainers[] = {
|
static const GUID* kAlphaContainers[] = {
|
||||||
&GUID_ContainerFormatBmp,
|
&GUID_ContainerFormatBmp, &GUID_ContainerFormatPng,
|
||||||
&GUID_ContainerFormatPng,
|
&GUID_ContainerFormatTiff, &GUID_ContainerFormatWebp_, NULL};
|
||||||
&GUID_ContainerFormatTiff,
|
|
||||||
&GUID_ContainerFormatWebp_,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
int has_alpha = 0;
|
int has_alpha = 0;
|
||||||
int64_t stride;
|
int64_t stride;
|
||||||
|
|
||||||
if (filename == NULL || pic == NULL) return 0;
|
if (filename == NULL || pic == NULL) return 0;
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
IFS(CoInitialize(NULL));
|
||||||
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
IFS(CoCreateInstance(
|
||||||
CLSCTX_INPROC_SERVER,
|
MAKE_REFGUID(CLSID_WICImagingFactory), NULL, CLSCTX_INPROC_SERVER,
|
||||||
MAKE_REFGUID(IID_IWICImagingFactory),
|
MAKE_REFGUID(IID_IWICImagingFactory), (LPVOID*)&factory));
|
||||||
(LPVOID*)&factory));
|
|
||||||
if (hr == REGDB_E_CLASSNOTREG) {
|
if (hr == REGDB_E_CLASSNOTREG) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Couldn't access Windows Imaging Component (are you running "
|
"Couldn't access Windows Imaging Component (are you running "
|
||||||
@@ -303,8 +287,7 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
// Prepare for image decoding.
|
// Prepare for image decoding.
|
||||||
IFS(OpenInputStream(filename, &stream));
|
IFS(OpenInputStream(filename, &stream));
|
||||||
IFS(IWICImagingFactory_CreateDecoderFromStream(
|
IFS(IWICImagingFactory_CreateDecoderFromStream(
|
||||||
factory, stream, NULL,
|
factory, stream, NULL, WICDecodeMetadataCacheOnDemand, &decoder));
|
||||||
WICDecodeMetadataCacheOnDemand, &decoder));
|
|
||||||
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
|
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
if (frame_count == 0) {
|
if (frame_count == 0) {
|
||||||
@@ -338,18 +321,15 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
hr == S_OK && importer->import != NULL; ++importer) {
|
hr == S_OK && importer->import != NULL; ++importer) {
|
||||||
BOOL can_convert;
|
BOOL can_convert;
|
||||||
const HRESULT cchr = IWICFormatConverter_CanConvert(
|
const HRESULT cchr = IWICFormatConverter_CanConvert(
|
||||||
converter,
|
converter, MAKE_REFGUID(src_pixel_format),
|
||||||
MAKE_REFGUID(src_pixel_format),
|
MAKE_REFGUID(*importer->pixel_format), &can_convert);
|
||||||
MAKE_REFGUID(*importer->pixel_format),
|
|
||||||
&can_convert);
|
|
||||||
if (SUCCEEDED(cchr) && can_convert) break;
|
if (SUCCEEDED(cchr) && can_convert) break;
|
||||||
}
|
}
|
||||||
if (importer->import == NULL) hr = E_FAIL;
|
if (importer->import == NULL) hr = E_FAIL;
|
||||||
|
|
||||||
IFS(IWICFormatConverter_Initialize(converter, (IWICBitmapSource*)frame,
|
IFS(IWICFormatConverter_Initialize(
|
||||||
importer->pixel_format,
|
converter, (IWICBitmapSource*)frame, importer->pixel_format,
|
||||||
WICBitmapDitherTypeNone,
|
WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom));
|
||||||
NULL, 0.0, WICBitmapPaletteTypeCustom));
|
|
||||||
|
|
||||||
// Decode.
|
// Decode.
|
||||||
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
||||||
@@ -361,11 +341,10 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
rgb = (BYTE*)malloc((size_t)stride * height);
|
rgb = (BYTE*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL)
|
if (rgb == NULL) hr = E_OUTOFMEMORY;
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
}
|
}
|
||||||
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
|
IFS(IWICFormatConverter_CopyPixels(converter, NULL, (UINT)stride,
|
||||||
(UINT)stride, (UINT)stride * height, rgb));
|
(UINT)stride * height, rgb));
|
||||||
|
|
||||||
// WebP conversion.
|
// WebP conversion.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@@ -402,7 +381,8 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr, "Windows Imaging Component (WIC) support not compiled. "
|
fprintf(stderr,
|
||||||
|
"Windows Imaging Component (WIC) support not compiled. "
|
||||||
"Visual Studio and mingw-w64 builds support WIC. Make sure "
|
"Visual Studio and mingw-w64 builds support WIC. Make sure "
|
||||||
"wincodec.h detection is working correctly if using autoconf "
|
"wincodec.h detection is working correctly if using autoconf "
|
||||||
"and HAVE_WINCODEC_H is defined before building.\n");
|
"and HAVE_WINCODEC_H is defined before building.\n");
|
||||||
|
|||||||
@@ -26,9 +26,7 @@
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int SharpYuvGetVersion(void) {
|
int SharpYuvGetVersion(void) { return SHARPYUV_VERSION; }
|
||||||
return SHARPYUV_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Sharp RGB->YUV conversion
|
// Sharp RGB->YUV conversion
|
||||||
@@ -148,12 +146,9 @@ static WEBP_INLINE int Shift(int v, int shift) {
|
|||||||
return (shift >= 0) ? (v << shift) : (v >> -shift);
|
return (shift >= 0) ? (v << shift) : (v >> -shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImportOneRow(const uint8_t* const r_ptr,
|
static void ImportOneRow(const uint8_t* const r_ptr, const uint8_t* const g_ptr,
|
||||||
const uint8_t* const g_ptr,
|
const uint8_t* const b_ptr, int rgb_step,
|
||||||
const uint8_t* const b_ptr,
|
int rgb_bit_depth, int pic_width,
|
||||||
int rgb_step,
|
|
||||||
int rgb_bit_depth,
|
|
||||||
int pic_width,
|
|
||||||
fixed_y_t* const dst) {
|
fixed_y_t* const dst) {
|
||||||
// Convert the rgb_step from a number of bytes to a number of uint8_t or
|
// Convert the rgb_step from a number of bytes to a number of uint8_t or
|
||||||
// uint16_t values depending the bit depth.
|
// uint16_t values depending the bit depth.
|
||||||
@@ -181,13 +176,9 @@ static void ImportOneRow(const uint8_t* const r_ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void InterpolateTwoRows(const fixed_y_t* const best_y,
|
static void InterpolateTwoRows(const fixed_y_t* const best_y,
|
||||||
const fixed_t* prev_uv,
|
const fixed_t* prev_uv, const fixed_t* cur_uv,
|
||||||
const fixed_t* cur_uv,
|
const fixed_t* next_uv, int w, fixed_y_t* out1,
|
||||||
const fixed_t* next_uv,
|
fixed_y_t* out2, int rgb_bit_depth) {
|
||||||
int w,
|
|
||||||
fixed_y_t* out1,
|
|
||||||
fixed_y_t* out2,
|
|
||||||
int rgb_bit_depth) {
|
|
||||||
const int uv_w = w >> 1;
|
const int uv_w = w >> 1;
|
||||||
const int len = (w - 1) >> 1; // length to filter
|
const int len = (w - 1) >> 1; // length to filter
|
||||||
int k = 3;
|
int k = 3;
|
||||||
@@ -220,16 +211,16 @@ static void InterpolateTwoRows(const fixed_y_t* const best_y,
|
|||||||
static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b,
|
static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b,
|
||||||
const int coeffs[4], int sfix) {
|
const int coeffs[4], int sfix) {
|
||||||
const int srounder = 1 << (YUV_FIX + sfix - 1);
|
const int srounder = 1 << (YUV_FIX + sfix - 1);
|
||||||
const int luma = coeffs[0] * r + coeffs[1] * g + coeffs[2] * b +
|
const int luma =
|
||||||
coeffs[3] + srounder;
|
coeffs[0] * r + coeffs[1] * g + coeffs[2] * b + coeffs[3] + srounder;
|
||||||
return (luma >> (YUV_FIX + sfix));
|
return (luma >> (YUV_FIX + sfix));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
|
static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
|
||||||
uint8_t* y_ptr, int y_stride, uint8_t* u_ptr,
|
uint8_t* y_ptr, int y_stride, uint8_t* u_ptr,
|
||||||
int u_stride, uint8_t* v_ptr, int v_stride,
|
int u_stride, uint8_t* v_ptr, int v_stride,
|
||||||
int rgb_bit_depth,
|
int rgb_bit_depth, int yuv_bit_depth, int width,
|
||||||
int yuv_bit_depth, int width, int height,
|
int height,
|
||||||
const SharpYuvConversionMatrix* yuv_matrix) {
|
const SharpYuvConversionMatrix* yuv_matrix) {
|
||||||
int i, j;
|
int i, j;
|
||||||
const fixed_t* const best_uv_base = best_uv;
|
const fixed_t* const best_uv_base = best_uv;
|
||||||
@@ -335,9 +326,8 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
|||||||
assert(w > 0);
|
assert(w > 0);
|
||||||
assert(h > 0);
|
assert(h > 0);
|
||||||
|
|
||||||
if (best_y_base == NULL || best_uv_base == NULL ||
|
if (best_y_base == NULL || best_uv_base == NULL || target_y_base == NULL ||
|
||||||
target_y_base == NULL || target_uv_base == NULL ||
|
target_uv_base == NULL || best_rgb_y == NULL || best_rgb_uv == NULL ||
|
||||||
best_rgb_y == NULL || best_rgb_uv == NULL ||
|
|
||||||
tmp_buffer == NULL) {
|
tmp_buffer == NULL) {
|
||||||
ok = 0;
|
ok = 0;
|
||||||
goto End;
|
goto End;
|
||||||
@@ -350,8 +340,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
|||||||
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
||||||
|
|
||||||
// prepare two rows of input
|
// prepare two rows of input
|
||||||
ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width,
|
ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width, src1);
|
||||||
src1);
|
|
||||||
if (!is_last_row) {
|
if (!is_last_row) {
|
||||||
ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
|
ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
|
||||||
rgb_step, rgb_bit_depth, width, src2);
|
rgb_step, rgb_bit_depth, width, src2);
|
||||||
@@ -390,8 +379,8 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
|||||||
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
||||||
{
|
{
|
||||||
const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
|
const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
|
||||||
InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w,
|
InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w, src1, src2,
|
||||||
src1, src2, rgb_bit_depth);
|
rgb_bit_depth);
|
||||||
prev_uv = cur_uv;
|
prev_uv = cur_uv;
|
||||||
cur_uv = next_uv;
|
cur_uv = next_uv;
|
||||||
}
|
}
|
||||||
@@ -424,7 +413,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
|||||||
u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth,
|
u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth,
|
||||||
width, height, yuv_matrix);
|
width, height, yuv_matrix);
|
||||||
|
|
||||||
End:
|
End:
|
||||||
free(best_y_base);
|
free(best_y_base);
|
||||||
free(best_uv_base);
|
free(best_uv_base);
|
||||||
free(target_y_base);
|
free(target_y_base);
|
||||||
@@ -449,7 +438,9 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
|||||||
return; \
|
return; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
|
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
|
||||||
#define LOCK_ACCESS do {} while (0)
|
#define LOCK_ACCESS \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
#define UNLOCK_ACCESS_AND_RETURN return
|
#define UNLOCK_ACCESS_AND_RETURN return
|
||||||
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
||||||
|
|
||||||
|
|||||||
@@ -67,8 +67,7 @@ void SharpYuvInitGammaTables(void) {
|
|||||||
} else {
|
} else {
|
||||||
value = (1. + a) * pow(g, 1. / kGammaF) - a;
|
value = (1. + a) * pow(g, 1. / kGammaF) - a;
|
||||||
}
|
}
|
||||||
kLinearToGammaTabS[v] =
|
kLinearToGammaTabS[v] = (uint32_t)(final_scale * value + 0.5);
|
||||||
(uint32_t)(final_scale * value + 0.5);
|
|
||||||
}
|
}
|
||||||
// to prevent small rounding errors to cause read-overflow:
|
// to prevent small rounding errors to cause read-overflow:
|
||||||
kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 1] =
|
kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 1] =
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
#include "sharpyuv/sharpyuv_dsp.h"
|
#include "sharpyuv/sharpyuv_dsp.h"
|
||||||
|
|
||||||
#if defined(WEBP_USE_NEON)
|
#if defined(WEBP_USE_NEON)
|
||||||
|
#include <arm_neon.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <arm_neon.h>
|
|
||||||
|
|
||||||
static uint16_t clip_NEON(int v, int max) {
|
static uint16_t clip_NEON(int v, int max) {
|
||||||
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#if defined(WEBP_USE_SSE2)
|
#if defined(WEBP_USE_SSE2)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
|
|||||||
@@ -79,8 +79,7 @@ WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
|||||||
if (dec->method < ALPHA_NO_COMPRESSION ||
|
if (dec->method < ALPHA_NO_COMPRESSION ||
|
||||||
dec->method > ALPHA_LOSSLESS_COMPRESSION ||
|
dec->method > ALPHA_LOSSLESS_COMPRESSION ||
|
||||||
dec->filter >= WEBP_FILTER_LAST ||
|
dec->filter >= WEBP_FILTER_LAST ||
|
||||||
dec->pre_processing > ALPHA_PREPROCESSED_LEVELS ||
|
dec->pre_processing > ALPHA_PREPROCESSED_LEVELS || rsrv != 0) {
|
||||||
rsrv != 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,12 +196,12 @@ WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!AllocateAlphaPlane(dec, io)) goto Error;
|
if (!AllocateAlphaPlane(dec, io)) goto Error;
|
||||||
if (!ALPHInit(dec->alph_dec, dec->alpha_data, dec->alpha_data_size,
|
if (!ALPHInit(dec->alph_dec, dec->alpha_data, dec->alpha_data_size, io,
|
||||||
io, dec->alpha_plane)) {
|
dec->alpha_plane)) {
|
||||||
VP8LDecoder* const vp8l_dec = dec->alph_dec->vp8l_dec;
|
VP8LDecoder* const vp8l_dec = dec->alph_dec->vp8l_dec;
|
||||||
VP8SetError(dec,
|
VP8SetError(
|
||||||
(vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY
|
dec,
|
||||||
: vp8l_dec->status,
|
(vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY : vp8l_dec->status,
|
||||||
"Alpha decoder initialization failed.");
|
"Alpha decoder initialization failed.");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
@@ -222,12 +221,11 @@ WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
|||||||
ALPHDelete(dec->alph_dec);
|
ALPHDelete(dec->alph_dec);
|
||||||
dec->alph_dec = NULL;
|
dec->alph_dec = NULL;
|
||||||
if (dec->alpha_dithering > 0) {
|
if (dec->alpha_dithering > 0) {
|
||||||
uint8_t* const alpha = dec->alpha_plane + io->crop_top * width
|
uint8_t* const alpha =
|
||||||
+ io->crop_left;
|
dec->alpha_plane + io->crop_top * width + io->crop_left;
|
||||||
if (!WebPDequantizeLevels(alpha,
|
if (!WebPDequantizeLevels(alpha, io->crop_right - io->crop_left,
|
||||||
io->crop_right - io->crop_left,
|
io->crop_bottom - io->crop_top, width,
|
||||||
io->crop_bottom - io->crop_top,
|
dec->alpha_dithering)) {
|
||||||
width, dec->alpha_dithering)) {
|
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +235,7 @@ WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
|||||||
// Return a pointer to the current decoded row.
|
// Return a pointer to the current decoded row.
|
||||||
return dec->alpha_plane + row * width;
|
return dec->alpha_plane + row * width;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPDeallocateAlphaMemory(dec);
|
WebPDeallocateAlphaMemory(dec);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
#define WEBP_DEC_ALPHAI_DEC_H_
|
#define WEBP_DEC_ALPHAI_DEC_H_
|
||||||
|
|
||||||
#include "src/dec/vp8_dec.h"
|
#include "src/dec/vp8_dec.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dec/webpi_dec.h"
|
#include "src/dec/webpi_dec.h"
|
||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
#include "src/utils/filters_utils.h"
|
#include "src/utils/filters_utils.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -26,10 +26,9 @@
|
|||||||
// WebPDecBuffer
|
// WebPDecBuffer
|
||||||
|
|
||||||
// Number of bytes per pixel for the different color-spaces.
|
// Number of bytes per pixel for the different color-spaces.
|
||||||
static const uint8_t kModeBpp[MODE_LAST] = {
|
static const uint8_t kModeBpp[MODE_LAST] = {3, 4, 3, 4, 4, 2, 2, //
|
||||||
3, 4, 3, 4, 4, 2, 2,
|
|
||||||
4, 4, 4, 2, // pre-multiplied modes
|
4, 4, 4, 2, // pre-multiplied modes
|
||||||
1, 1 };
|
1, 1};
|
||||||
|
|
||||||
// Convert to an integer to handle both the unsigned/signed enum cases
|
// Convert to an integer to handle both the unsigned/signed enum cases
|
||||||
// without the need for casting to remove type limit warnings.
|
// without the need for casting to remove type limit warnings.
|
||||||
@@ -202,8 +201,8 @@ VP8StatusCode WebPAllocateDecBuffer(int width, int height,
|
|||||||
#if !defined(WEBP_REDUCE_SIZE)
|
#if !defined(WEBP_REDUCE_SIZE)
|
||||||
int scaled_width = options->scaled_width;
|
int scaled_width = options->scaled_width;
|
||||||
int scaled_height = options->scaled_height;
|
int scaled_height = options->scaled_height;
|
||||||
if (!WebPRescalerGetScaledDimensions(
|
if (!WebPRescalerGetScaledDimensions(width, height, &scaled_width,
|
||||||
width, height, &scaled_width, &scaled_height)) {
|
&scaled_height)) {
|
||||||
return VP8_STATUS_INVALID_PARAM;
|
return VP8_STATUS_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
width = scaled_width;
|
width = scaled_width;
|
||||||
@@ -289,8 +288,8 @@ VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src_buf,
|
|||||||
} else {
|
} else {
|
||||||
const WebPYUVABuffer* const src = &src_buf->u.YUVA;
|
const WebPYUVABuffer* const src = &src_buf->u.YUVA;
|
||||||
const WebPYUVABuffer* const dst = &dst_buf->u.YUVA;
|
const WebPYUVABuffer* const dst = &dst_buf->u.YUVA;
|
||||||
WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride,
|
WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride, src_buf->width,
|
||||||
src_buf->width, src_buf->height);
|
src_buf->height);
|
||||||
WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride,
|
WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride,
|
||||||
(src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
|
(src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
|
||||||
WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride,
|
WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride,
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
#define WEBP_DEC_COMMON_DEC_H_
|
#define WEBP_DEC_COMMON_DEC_H_
|
||||||
|
|
||||||
// intra prediction modes
|
// intra prediction modes
|
||||||
enum { B_DC_PRED = 0, // 4x4 modes
|
enum {
|
||||||
|
B_DC_PRED = 0, // 4x4 modes
|
||||||
B_TM_PRED = 1,
|
B_TM_PRED = 1,
|
||||||
B_VE_PRED = 2,
|
B_VE_PRED = 2,
|
||||||
B_HE_PRED = 3,
|
B_HE_PRED = 3,
|
||||||
@@ -28,8 +29,10 @@ enum { B_DC_PRED = 0, // 4x4 modes
|
|||||||
NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
|
NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
|
||||||
|
|
||||||
// Luma16 or UV modes
|
// Luma16 or UV modes
|
||||||
DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
|
DC_PRED = B_DC_PRED,
|
||||||
H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
|
V_PRED = B_VE_PRED,
|
||||||
|
H_PRED = B_HE_PRED,
|
||||||
|
TM_PRED = B_TM_PRED,
|
||||||
B_PRED = NUM_BMODES, // refined I4x4 mode
|
B_PRED = NUM_BMODES, // refined I4x4 mode
|
||||||
NUM_PRED_MODES = 4,
|
NUM_PRED_MODES = 4,
|
||||||
|
|
||||||
@@ -37,9 +40,11 @@ enum { B_DC_PRED = 0, // 4x4 modes
|
|||||||
B_DC_PRED_NOTOP = 4,
|
B_DC_PRED_NOTOP = 4,
|
||||||
B_DC_PRED_NOLEFT = 5,
|
B_DC_PRED_NOLEFT = 5,
|
||||||
B_DC_PRED_NOTOPLEFT = 6,
|
B_DC_PRED_NOTOPLEFT = 6,
|
||||||
NUM_B_DC_MODES = 7 };
|
NUM_B_DC_MODES = 7
|
||||||
|
};
|
||||||
|
|
||||||
enum { MB_FEATURE_TREE_PROBS = 3,
|
enum {
|
||||||
|
MB_FEATURE_TREE_PROBS = 3,
|
||||||
NUM_MB_SEGMENTS = 4,
|
NUM_MB_SEGMENTS = 4,
|
||||||
NUM_REF_LF_DELTAS = 4,
|
NUM_REF_LF_DELTAS = 4,
|
||||||
NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
|
NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
|
||||||
@@ -49,7 +54,7 @@ enum { MB_FEATURE_TREE_PROBS = 3,
|
|||||||
NUM_BANDS = 8,
|
NUM_BANDS = 8,
|
||||||
NUM_CTX = 3,
|
NUM_CTX = 3,
|
||||||
NUM_PROBAS = 11
|
NUM_PROBAS = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
|
// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
|
||||||
int IsValidColorspace(int webp_csp_mode);
|
int IsValidColorspace(int webp_csp_mode);
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ static const uint16_t kScan[16] = {
|
|||||||
0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
|
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 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
|
||||||
0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * 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 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS};
|
||||||
};
|
|
||||||
|
|
||||||
static int CheckMode(int mb_x, int mb_y, int mode) {
|
static int CheckMode(int mb_x, int mb_y, int mode) {
|
||||||
if (mode == B_DC_PRED) {
|
if (mode == B_DC_PRED) {
|
||||||
@@ -209,7 +208,7 @@ static void ReconstructRow(const VP8Decoder* const dec,
|
|||||||
// Simple filter: up to 2 luma samples are read and 1 is written.
|
// 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
|
// 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).
|
// U/V, so it's 8 samples total (because of the 2x upsampling).
|
||||||
static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 };
|
static const uint8_t kFilterExtraRows[3] = {0, 2, 8};
|
||||||
|
|
||||||
static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
|
static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
|
||||||
const VP8ThreadContext* const ctx = &dec->thread_ctx;
|
const VP8ThreadContext* const ctx = &dec->thread_ctx;
|
||||||
@@ -333,8 +332,7 @@ static void PrecomputeFilterStrengths(VP8Decoder* const dec) {
|
|||||||
#define DITHER_AMP_TAB_SIZE 12
|
#define DITHER_AMP_TAB_SIZE 12
|
||||||
static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = {
|
static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = {
|
||||||
// roughly, it's dqm->uv_mat[1]
|
// roughly, it's dqm->uv_mat[1]
|
||||||
8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1
|
8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1};
|
||||||
};
|
|
||||||
|
|
||||||
void VP8InitDithering(const WebPDecoderOptions* const options,
|
void VP8InitDithering(const WebPDecoderOptions* const options,
|
||||||
VP8Decoder* const dec) {
|
VP8Decoder* const dec) {
|
||||||
@@ -512,9 +510,9 @@ static int FinishRow(void* arg1, void* arg2) {
|
|||||||
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
|
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
VP8ThreadContext* const ctx = &dec->thread_ctx;
|
VP8ThreadContext* const ctx = &dec->thread_ctx;
|
||||||
const int filter_row =
|
const int filter_row = (dec->filter_type > 0) &&
|
||||||
(dec->filter_type > 0) &&
|
(dec->mb_y >= dec->tl_mb_y) &&
|
||||||
(dec->mb_y >= dec->tl_mb_y) && (dec->mb_y <= dec->br_mb_y);
|
(dec->mb_y <= dec->br_mb_y);
|
||||||
if (dec->mt_method == 0) {
|
if (dec->mt_method == 0) {
|
||||||
// ctx->id and ctx->f_info are already set
|
// ctx->id and ctx->f_info are already set
|
||||||
ctx->mb_y = dec->mb_y;
|
ctx->mb_y = dec->mb_y;
|
||||||
@@ -669,8 +667,8 @@ static int InitThreadContext(VP8Decoder* const dec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
|
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
|
||||||
const WebPHeaderStructure* const headers,
|
const WebPHeaderStructure* const headers, int width,
|
||||||
int width, int height) {
|
int height) {
|
||||||
if (options == NULL || options->use_threads == 0) {
|
if (options == NULL || options->use_threads == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -698,22 +696,23 @@ static int AllocateMemory(VP8Decoder* const dec) {
|
|||||||
const size_t top_size = sizeof(VP8TopSamples) * mb_w;
|
const size_t top_size = sizeof(VP8TopSamples) * mb_w;
|
||||||
const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB);
|
const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB);
|
||||||
const size_t f_info_size =
|
const size_t f_info_size =
|
||||||
(dec->filter_type > 0) ?
|
(dec->filter_type > 0)
|
||||||
mb_w * (dec->mt_method > 0 ? 2 : 1) * sizeof(VP8FInfo)
|
? mb_w * (dec->mt_method > 0 ? 2 : 1) * sizeof(VP8FInfo)
|
||||||
: 0;
|
: 0;
|
||||||
const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b);
|
const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b);
|
||||||
const size_t mb_data_size =
|
const size_t mb_data_size =
|
||||||
(dec->mt_method == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data);
|
(dec->mt_method == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data);
|
||||||
const size_t cache_height = (16 * num_caches
|
const size_t cache_height =
|
||||||
+ kFilterExtraRows[dec->filter_type]) * 3 / 2;
|
(16 * num_caches + kFilterExtraRows[dec->filter_type]) * 3 / 2;
|
||||||
const size_t cache_size = top_size * cache_height;
|
const size_t cache_size = top_size * cache_height;
|
||||||
// alpha_size is the only one that scales as width x height.
|
// alpha_size is the only one that scales as width x height.
|
||||||
const uint64_t alpha_size = (dec->alpha_data != NULL) ?
|
const uint64_t alpha_size =
|
||||||
(uint64_t)dec->pic_hdr.width * dec->pic_hdr.height : 0ULL;
|
(dec->alpha_data != NULL)
|
||||||
const uint64_t needed = (uint64_t)intra_pred_mode_size
|
? (uint64_t)dec->pic_hdr.width * dec->pic_hdr.height
|
||||||
+ top_size + mb_info_size + f_info_size
|
: 0ULL;
|
||||||
+ yuv_size + mb_data_size
|
const uint64_t needed = (uint64_t)intra_pred_mode_size + top_size +
|
||||||
+ cache_size + alpha_size + WEBP_ALIGN_CST;
|
mb_info_size + f_info_size + yuv_size + mb_data_size +
|
||||||
|
cache_size + alpha_size + WEBP_ALIGN_CST;
|
||||||
uint8_t* mem;
|
uint8_t* mem;
|
||||||
|
|
||||||
if (!CheckSizeOverflow(needed)) return 0; // check for overflow
|
if (!CheckSizeOverflow(needed)) return 0; // check for overflow
|
||||||
@@ -769,10 +768,10 @@ static int AllocateMemory(VP8Decoder* const dec) {
|
|||||||
const int extra_y = extra_rows * dec->cache_y_stride;
|
const int extra_y = extra_rows * dec->cache_y_stride;
|
||||||
const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride;
|
const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride;
|
||||||
dec->cache_y = mem + extra_y;
|
dec->cache_y = mem + extra_y;
|
||||||
dec->cache_u = dec->cache_y
|
dec->cache_u =
|
||||||
+ 16 * num_caches * dec->cache_y_stride + extra_uv;
|
dec->cache_y + 16 * num_caches * dec->cache_y_stride + extra_uv;
|
||||||
dec->cache_v = dec->cache_u
|
dec->cache_v =
|
||||||
+ 8 * num_caches * dec->cache_uv_stride + extra_uv;
|
dec->cache_u + 8 * num_caches * dec->cache_uv_stride + extra_uv;
|
||||||
dec->cache_id = 0;
|
dec->cache_id = 0;
|
||||||
}
|
}
|
||||||
mem += cache_size;
|
mem += cache_size;
|
||||||
|
|||||||
@@ -51,11 +51,7 @@ typedef enum {
|
|||||||
} DecState;
|
} DecState;
|
||||||
|
|
||||||
// Operating state for the MemBuffer
|
// Operating state for the MemBuffer
|
||||||
typedef enum {
|
typedef enum { MEM_MODE_NONE = 0, MEM_MODE_APPEND, MEM_MODE_MAP } MemBufferMode;
|
||||||
MEM_MODE_NONE = 0,
|
|
||||||
MEM_MODE_APPEND,
|
|
||||||
MEM_MODE_MAP
|
|
||||||
} MemBufferMode;
|
|
||||||
|
|
||||||
// storage for partition #0 and partial data (in a rolling fashion)
|
// storage for partition #0 and partial data (in a rolling fashion)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -437,14 +433,14 @@ static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate/Verify output buffer now
|
// Allocate/Verify output buffer now
|
||||||
dec->status = WebPAllocateDecBuffer(io->width, io->height, params->options,
|
dec->status =
|
||||||
output);
|
WebPAllocateDecBuffer(io->width, io->height, params->options, output);
|
||||||
if (dec->status != VP8_STATUS_OK) {
|
if (dec->status != VP8_STATUS_OK) {
|
||||||
return IDecError(idec, dec->status);
|
return IDecError(idec, dec->status);
|
||||||
}
|
}
|
||||||
// This change must be done before calling VP8InitFrame()
|
// This change must be done before calling VP8InitFrame()
|
||||||
dec->mt_method = VP8GetThreadMethod(params->options, NULL,
|
dec->mt_method =
|
||||||
io->width, io->height);
|
VP8GetThreadMethod(params->options, NULL, io->width, io->height);
|
||||||
VP8InitDithering(params->options, dec);
|
VP8InitDithering(params->options, dec);
|
||||||
|
|
||||||
dec->status = CopyParts0Data(idec);
|
dec->status = CopyParts0Data(idec);
|
||||||
@@ -558,8 +554,8 @@ static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) {
|
|||||||
return ErrorStatusLossless(idec, dec->status);
|
return ErrorStatusLossless(idec, dec->status);
|
||||||
}
|
}
|
||||||
// Allocate/verify output buffer now.
|
// Allocate/verify output buffer now.
|
||||||
dec->status = WebPAllocateDecBuffer(io->width, io->height, params->options,
|
dec->status =
|
||||||
output);
|
WebPAllocateDecBuffer(io->width, io->height, params->options, output);
|
||||||
if (dec->status != VP8_STATUS_OK) {
|
if (dec->status != VP8_STATUS_OK) {
|
||||||
return IDecError(idec, dec->status);
|
return IDecError(idec, dec->status);
|
||||||
}
|
}
|
||||||
@@ -584,7 +580,7 @@ static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
|
|||||||
: FinishDecoding(idec);
|
: FinishDecoding(idec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main decoding loop
|
// Main decoding loop
|
||||||
static VP8StatusCode IDecode(WebPIDecoder* idec) {
|
static VP8StatusCode IDecode(WebPIDecoder* idec) {
|
||||||
VP8StatusCode status = VP8_STATUS_SUSPENDED;
|
VP8StatusCode status = VP8_STATUS_SUSPENDED;
|
||||||
|
|
||||||
@@ -737,9 +733,9 @@ WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
|
WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
|
||||||
uint8_t* u, size_t u_size, int u_stride,
|
uint8_t* u, size_t u_size, int u_stride, uint8_t* v,
|
||||||
uint8_t* v, size_t v_size, int v_stride,
|
size_t v_size, int v_stride, uint8_t* a,
|
||||||
uint8_t* a, size_t a_size, int a_stride) {
|
size_t a_size, int a_stride) {
|
||||||
const int is_external_memory = (luma != NULL) ? 1 : 0;
|
const int is_external_memory = (luma != NULL) ? 1 : 0;
|
||||||
WebPIDecoder* idec;
|
WebPIDecoder* idec;
|
||||||
WEBP_CSP_MODE colorspace;
|
WEBP_CSP_MODE colorspace;
|
||||||
@@ -780,12 +776,10 @@ WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
|
WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
|
||||||
uint8_t* u, size_t u_size, int u_stride,
|
uint8_t* u, size_t u_size, int u_stride, uint8_t* v,
|
||||||
uint8_t* v, size_t v_size, int v_stride) {
|
size_t v_size, int v_stride) {
|
||||||
return WebPINewYUVA(luma, luma_size, luma_stride,
|
return WebPINewYUVA(luma, luma_size, luma_stride, u, u_size, u_stride, v,
|
||||||
u, u_size, u_stride,
|
v_size, v_stride, NULL, 0, 0);
|
||||||
v, v_size, v_stride,
|
|
||||||
NULL, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -801,8 +795,8 @@ static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) {
|
|||||||
return VP8_STATUS_SUSPENDED;
|
return VP8_STATUS_SUSPENDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8StatusCode WebPIAppend(WebPIDecoder* idec,
|
VP8StatusCode WebPIAppend(WebPIDecoder* idec, const uint8_t* data,
|
||||||
const uint8_t* data, size_t data_size) {
|
size_t data_size) {
|
||||||
VP8StatusCode status;
|
VP8StatusCode status;
|
||||||
if (idec == NULL || data == NULL) {
|
if (idec == NULL || data == NULL) {
|
||||||
return VP8_STATUS_INVALID_PARAM;
|
return VP8_STATUS_INVALID_PARAM;
|
||||||
@@ -822,8 +816,8 @@ VP8StatusCode WebPIAppend(WebPIDecoder* idec,
|
|||||||
return IDecode(idec);
|
return IDecode(idec);
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8StatusCode WebPIUpdate(WebPIDecoder* idec,
|
VP8StatusCode WebPIUpdate(WebPIDecoder* idec, const uint8_t* data,
|
||||||
const uint8_t* data, size_t data_size) {
|
size_t data_size) {
|
||||||
VP8StatusCode status;
|
VP8StatusCode status;
|
||||||
if (idec == NULL || data == NULL) {
|
if (idec == NULL || data == NULL) {
|
||||||
return VP8_STATUS_INVALID_PARAM;
|
return VP8_STATUS_INVALID_PARAM;
|
||||||
@@ -858,9 +852,8 @@ static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) {
|
|||||||
return idec->params.output;
|
return idec->params.output;
|
||||||
}
|
}
|
||||||
|
|
||||||
const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
|
const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, int* left,
|
||||||
int* left, int* top,
|
int* top, int* width, int* height) {
|
||||||
int* width, int* height) {
|
|
||||||
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
||||||
if (left != NULL) *left = 0;
|
if (left != NULL) *left = 0;
|
||||||
if (top != NULL) *top = 0;
|
if (top != NULL) *top = 0;
|
||||||
@@ -913,10 +906,8 @@ WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
|
|||||||
return src->u.YUVA.y;
|
return src->u.YUVA.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPISetIOHooks(WebPIDecoder* const idec,
|
int WebPISetIOHooks(WebPIDecoder* const idec, VP8IoPutHook put,
|
||||||
VP8IoPutHook put,
|
VP8IoSetupHook setup, VP8IoTeardownHook teardown,
|
||||||
VP8IoSetupHook setup,
|
|
||||||
VP8IoTeardownHook teardown,
|
|
||||||
void* user_data) {
|
void* user_data) {
|
||||||
if (idec == NULL || idec->state > STATE_WEBP_HEADER) {
|
if (idec == NULL || idec->state > STATE_WEBP_HEADER) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "src/dec/vp8_dec.h"
|
#include "src/dec/vp8_dec.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dec/vp8i_dec.h"
|
#include "src/dec/vp8i_dec.h"
|
||||||
#include "src/dec/webpi_dec.h"
|
#include "src/dec/webpi_dec.h"
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
@@ -26,6 +25,7 @@
|
|||||||
#include "src/utils/rescaler_utils.h"
|
#include "src/utils/rescaler_utils.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/utils/utils.h"
|
||||||
#include "src/webp/decode.h"
|
#include "src/webp/decode.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Main YUV<->RGB conversion functions
|
// Main YUV<->RGB conversion functions
|
||||||
@@ -51,9 +51,8 @@ static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
WebPDecBuffer* const output = p->output;
|
WebPDecBuffer* const output = p->output;
|
||||||
WebPRGBABuffer* const buf = &output->u.RGBA;
|
WebPRGBABuffer* const buf = &output->u.RGBA;
|
||||||
uint8_t* const dst = buf->rgba + (ptrdiff_t)io->mb_y * buf->stride;
|
uint8_t* const dst = buf->rgba + (ptrdiff_t)io->mb_y * buf->stride;
|
||||||
WebPSamplerProcessPlane(io->y, io->y_stride,
|
WebPSamplerProcessPlane(io->y, io->y_stride, io->u, io->v, io->uv_stride, dst,
|
||||||
io->u, io->v, io->uv_stride,
|
buf->stride, io->mb_w, io->mb_h,
|
||||||
dst, buf->stride, io->mb_w, io->mb_h,
|
|
||||||
WebPSamplers[output->colorspace]);
|
WebPSamplers[output->colorspace]);
|
||||||
return io->mb_h;
|
return io->mb_h;
|
||||||
}
|
}
|
||||||
@@ -82,8 +81,8 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w);
|
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w);
|
||||||
} else {
|
} else {
|
||||||
// We can finish the left-over line from previous call.
|
// We can finish the left-over line from previous call.
|
||||||
upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
|
upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, dst - buf->stride,
|
||||||
dst - buf->stride, dst, mb_w);
|
dst, mb_w);
|
||||||
++num_lines_out;
|
++num_lines_out;
|
||||||
}
|
}
|
||||||
// Loop over each output pairs of row.
|
// Loop over each output pairs of row.
|
||||||
@@ -94,8 +93,7 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
cur_v += io->uv_stride;
|
cur_v += io->uv_stride;
|
||||||
dst += 2 * buf->stride;
|
dst += 2 * buf->stride;
|
||||||
cur_y += 2 * io->y_stride;
|
cur_y += 2 * io->y_stride;
|
||||||
upsample(cur_y - io->y_stride, cur_y,
|
upsample(cur_y - io->y_stride, cur_y, top_u, top_v, cur_u, cur_v,
|
||||||
top_u, top_v, cur_u, cur_v,
|
|
||||||
dst - buf->stride, dst, mb_w);
|
dst - buf->stride, dst, mb_w);
|
||||||
}
|
}
|
||||||
// move to last row
|
// move to last row
|
||||||
@@ -111,8 +109,8 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
} else {
|
} else {
|
||||||
// Process the very last row of even-sized picture
|
// Process the very last row of even-sized picture
|
||||||
if (!(y_end & 1)) {
|
if (!(y_end & 1)) {
|
||||||
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v,
|
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst + buf->stride, NULL,
|
||||||
dst + buf->stride, NULL, mb_w);
|
mb_w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return num_lines_out;
|
return num_lines_out;
|
||||||
@@ -153,8 +151,8 @@ static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetAlphaSourceRow(const VP8Io* const io,
|
static int GetAlphaSourceRow(const VP8Io* const io, const uint8_t** alpha,
|
||||||
const uint8_t** alpha, int* const num_rows) {
|
int* const num_rows) {
|
||||||
int start_y = io->mb_y;
|
int start_y = io->mb_y;
|
||||||
*num_rows = io->mb_h;
|
*num_rows = io->mb_h;
|
||||||
|
|
||||||
@@ -192,14 +190,14 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
|
|||||||
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
|
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
|
||||||
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)start_y * buf->stride;
|
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)start_y * buf->stride;
|
||||||
uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
|
uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
|
||||||
const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
|
const int has_alpha =
|
||||||
num_rows, dst, buf->stride);
|
WebPDispatchAlpha(alpha, io->width, mb_w, num_rows, dst, buf->stride);
|
||||||
(void)expected_num_lines_out;
|
(void)expected_num_lines_out;
|
||||||
assert(expected_num_lines_out == num_rows);
|
assert(expected_num_lines_out == num_rows);
|
||||||
// has_alpha is true if there's non-trivial alpha to premultiply with.
|
// has_alpha is true if there's non-trivial alpha to premultiply with.
|
||||||
if (has_alpha && WebPIsPremultipliedMode(colorspace)) {
|
if (has_alpha && WebPIsPremultipliedMode(colorspace)) {
|
||||||
WebPApplyAlphaMultiply(base_rgba, alpha_first,
|
WebPApplyAlphaMultiply(base_rgba, alpha_first, mb_w, num_rows,
|
||||||
mb_w, num_rows, buf->stride);
|
buf->stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -245,8 +243,8 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
|
|||||||
// YUV rescaling (no final RGB conversion needed)
|
// YUV rescaling (no final RGB conversion needed)
|
||||||
|
|
||||||
#if !defined(WEBP_REDUCE_SIZE)
|
#if !defined(WEBP_REDUCE_SIZE)
|
||||||
static int Rescale(const uint8_t* src, int src_stride,
|
static int Rescale(const uint8_t* src, int src_stride, int new_lines,
|
||||||
int new_lines, WebPRescaler* const wrk) {
|
WebPRescaler* const wrk) {
|
||||||
int num_lines_out = 0;
|
int num_lines_out = 0;
|
||||||
while (new_lines > 0) { // import new contributions of source rows.
|
while (new_lines > 0) { // import new contributions of source rows.
|
||||||
const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
|
const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
|
||||||
@@ -267,8 +265,8 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
// internal buffer. This is OK since these samples are not used for
|
// internal buffer. This is OK since these samples are not used for
|
||||||
// intra-prediction (the top samples are saved in cache_y/u/v).
|
// intra-prediction (the top samples are saved in cache_y/u/v).
|
||||||
// But we need to cast the const away, though.
|
// But we need to cast the const away, though.
|
||||||
WebPMultRows((uint8_t*)io->y, io->y_stride,
|
WebPMultRows((uint8_t*)io->y, io->y_stride, io->a, io->width, io->mb_w,
|
||||||
io->a, io->width, io->mb_w, mb_h, 0);
|
mb_h, 0);
|
||||||
}
|
}
|
||||||
num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
|
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->u, io->uv_stride, uv_mb_h, p->scaler_u);
|
||||||
@@ -331,29 +329,28 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
}
|
}
|
||||||
work = (rescaler_t*)p->memory;
|
work = (rescaler_t*)p->memory;
|
||||||
|
|
||||||
scalers = (WebPRescaler*)WEBP_ALIGN(
|
scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + total_size -
|
||||||
(const uint8_t*)work + total_size - rescaler_size);
|
rescaler_size);
|
||||||
p->scaler_y = &scalers[0];
|
p->scaler_y = &scalers[0];
|
||||||
p->scaler_u = &scalers[1];
|
p->scaler_u = &scalers[1];
|
||||||
p->scaler_v = &scalers[2];
|
p->scaler_v = &scalers[2];
|
||||||
p->scaler_a = has_alpha ? &scalers[3] : NULL;
|
p->scaler_a = has_alpha ? &scalers[3] : NULL;
|
||||||
|
|
||||||
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
|
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h, buf->y, out_width,
|
||||||
buf->y, out_width, out_height, buf->y_stride, 1,
|
out_height, buf->y_stride, 1, work) ||
|
||||||
work) ||
|
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height, buf->u,
|
||||||
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
|
uv_out_width, uv_out_height, buf->u_stride, 1,
|
||||||
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
|
|
||||||
work + work_size) ||
|
work + work_size) ||
|
||||||
!WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
|
!WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height, buf->v,
|
||||||
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
|
uv_out_width, uv_out_height, buf->v_stride, 1,
|
||||||
work + work_size + uv_work_size)) {
|
work + work_size + uv_work_size)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
p->emit = EmitRescaledYUV;
|
p->emit = EmitRescaledYUV;
|
||||||
|
|
||||||
if (has_alpha) {
|
if (has_alpha) {
|
||||||
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
|
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h, buf->a, out_width,
|
||||||
buf->a, out_width, out_height, buf->a_stride, 1,
|
out_height, buf->a_stride, 1,
|
||||||
work + work_size + 2 * uv_work_size)) {
|
work + work_size + 2 * uv_work_size)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -381,8 +378,8 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
|
|||||||
WebPRescalerExportRow(p->scaler_y);
|
WebPRescalerExportRow(p->scaler_y);
|
||||||
WebPRescalerExportRow(p->scaler_u);
|
WebPRescalerExportRow(p->scaler_u);
|
||||||
WebPRescalerExportRow(p->scaler_v);
|
WebPRescalerExportRow(p->scaler_v);
|
||||||
convert(p->scaler_y->dst, p->scaler_u->dst, p->scaler_v->dst,
|
convert(p->scaler_y->dst, p->scaler_u->dst, p->scaler_v->dst, dst,
|
||||||
dst, p->scaler_y->dst_width);
|
p->scaler_y->dst_width);
|
||||||
dst += buf->stride;
|
dst += buf->stride;
|
||||||
++num_lines_out;
|
++num_lines_out;
|
||||||
}
|
}
|
||||||
@@ -419,8 +416,7 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
|
|||||||
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
||||||
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)y_pos * buf->stride;
|
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)y_pos * buf->stride;
|
||||||
const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
||||||
const int alpha_first =
|
const int alpha_first = (colorspace == MODE_ARGB || colorspace == MODE_Argb);
|
||||||
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
|
|
||||||
uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
|
uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
|
||||||
int num_lines_out = 0;
|
int num_lines_out = 0;
|
||||||
const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
|
const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
|
||||||
@@ -436,8 +432,8 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
|
|||||||
++num_lines_out;
|
++num_lines_out;
|
||||||
}
|
}
|
||||||
if (is_premult_alpha && non_opaque) {
|
if (is_premult_alpha && non_opaque) {
|
||||||
WebPApplyAlphaMultiply(base_rgba, alpha_first,
|
WebPApplyAlphaMultiply(base_rgba, alpha_first, width, num_lines_out,
|
||||||
width, num_lines_out, buf->stride);
|
buf->stride);
|
||||||
}
|
}
|
||||||
return num_lines_out;
|
return num_lines_out;
|
||||||
}
|
}
|
||||||
@@ -524,16 +520,15 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
work = (rescaler_t*)p->memory;
|
work = (rescaler_t*)p->memory;
|
||||||
tmp = (uint8_t*)(work + tmp_size1);
|
tmp = (uint8_t*)(work + tmp_size1);
|
||||||
|
|
||||||
scalers = (WebPRescaler*)WEBP_ALIGN(
|
scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + total_size -
|
||||||
(const uint8_t*)work + total_size - rescaler_size);
|
rescaler_size);
|
||||||
p->scaler_y = &scalers[0];
|
p->scaler_y = &scalers[0];
|
||||||
p->scaler_u = &scalers[1];
|
p->scaler_u = &scalers[1];
|
||||||
p->scaler_v = &scalers[2];
|
p->scaler_v = &scalers[2];
|
||||||
p->scaler_a = has_alpha ? &scalers[3] : NULL;
|
p->scaler_a = has_alpha ? &scalers[3] : NULL;
|
||||||
|
|
||||||
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
|
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h, tmp + 0 * out_width,
|
||||||
tmp + 0 * out_width, out_width, out_height, 0, 1,
|
out_width, out_height, 0, 1, work + 0 * work_size) ||
|
||||||
work + 0 * work_size) ||
|
|
||||||
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
|
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
|
||||||
tmp + 1 * out_width, out_width, out_height, 0, 1,
|
tmp + 1 * out_width, out_width, out_height, 0, 1,
|
||||||
work + 1 * work_size) ||
|
work + 1 * work_size) ||
|
||||||
@@ -546,9 +541,8 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
|||||||
WebPInitYUV444Converters();
|
WebPInitYUV444Converters();
|
||||||
|
|
||||||
if (has_alpha) {
|
if (has_alpha) {
|
||||||
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
|
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h, tmp + 3 * out_width,
|
||||||
tmp + 3 * out_width, out_width, out_height, 0, 1,
|
out_width, out_height, 0, 1, work + 3 * work_size)) {
|
||||||
work + 3 * work_size)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
p->emit_alpha = EmitRescaledAlphaRGB;
|
p->emit_alpha = EmitRescaledAlphaRGB;
|
||||||
@@ -616,8 +610,8 @@ static int CustomSetup(VP8Io* io) {
|
|||||||
}
|
}
|
||||||
if (is_alpha) { // need transparency output
|
if (is_alpha) { // need transparency output
|
||||||
p->emit_alpha =
|
p->emit_alpha =
|
||||||
(colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
|
(colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444)
|
||||||
EmitAlphaRGBA4444
|
? EmitAlphaRGBA4444
|
||||||
: is_rgb ? EmitAlphaRGB
|
: is_rgb ? EmitAlphaRGB
|
||||||
: EmitAlphaYUV;
|
: EmitAlphaYUV;
|
||||||
if (is_rgb) {
|
if (is_rgb) {
|
||||||
|
|||||||
@@ -17,48 +17,30 @@
|
|||||||
#include "src/utils/bit_reader_utils.h"
|
#include "src/utils/bit_reader_utils.h"
|
||||||
#include "src/webp/types.h"
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
static WEBP_INLINE int clip(int v, int M) {
|
static WEBP_INLINE int clip(int v, int M) { return v < 0 ? 0 : v > M ? M : v; }
|
||||||
return v < 0 ? 0 : v > M ? M : v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paragraph 14.1
|
// Paragraph 14.1
|
||||||
static const uint8_t kDcTable[128] = {
|
static const uint8_t kDcTable[128] = {
|
||||||
4, 5, 6, 7, 8, 9, 10, 10,
|
4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||||
11, 12, 13, 14, 15, 16, 17, 17,
|
17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26,
|
||||||
18, 19, 20, 20, 21, 21, 22, 22,
|
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40,
|
||||||
23, 23, 24, 25, 25, 26, 27, 28,
|
41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54,
|
||||||
29, 30, 31, 32, 33, 34, 35, 36,
|
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
|
||||||
37, 37, 38, 39, 40, 41, 42, 43,
|
70, 71, 72, 73, 74, 75, 76, 76, 77, 78, 79, 80, 81, 82, 83,
|
||||||
44, 45, 46, 46, 47, 48, 49, 50,
|
84, 85, 86, 87, 88, 89, 91, 93, 95, 96, 98, 100, 101, 102, 104,
|
||||||
51, 52, 53, 54, 55, 56, 57, 58,
|
106, 108, 110, 112, 114, 116, 118, 122, 124, 126, 128, 130, 132, 134, 136,
|
||||||
59, 60, 61, 62, 63, 64, 65, 66,
|
138, 140, 143, 145, 148, 151, 154, 157};
|
||||||
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] = {
|
static const uint16_t kAcTable[128] = {
|
||||||
4, 5, 6, 7, 8, 9, 10, 11,
|
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||||
12, 13, 14, 15, 16, 17, 18, 19,
|
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||||
20, 21, 22, 23, 24, 25, 26, 27,
|
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||||
28, 29, 30, 31, 32, 33, 34, 35,
|
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, 64, 66, 68,
|
||||||
36, 37, 38, 39, 40, 41, 42, 43,
|
70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98,
|
||||||
44, 45, 46, 47, 48, 49, 50, 51,
|
100, 102, 104, 106, 108, 110, 112, 114, 116, 119, 122, 125, 128, 131, 134,
|
||||||
52, 53, 54, 55, 56, 57, 58, 60,
|
137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 177, 181,
|
||||||
62, 64, 66, 68, 70, 72, 74, 76,
|
185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 234, 239, 245,
|
||||||
78, 80, 82, 84, 86, 88, 90, 92,
|
249, 254, 259, 264, 269, 274, 279, 284};
|
||||||
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
|
// Paragraph 9.6
|
||||||
@@ -66,16 +48,21 @@ static const uint16_t kAcTable[128] = {
|
|||||||
void VP8ParseQuant(VP8Decoder* const dec) {
|
void VP8ParseQuant(VP8Decoder* const dec) {
|
||||||
VP8BitReader* const br = &dec->br;
|
VP8BitReader* const br = &dec->br;
|
||||||
const int base_q0 = VP8GetValue(br, 7, "global-header");
|
const int base_q0 = VP8GetValue(br, 7, "global-header");
|
||||||
const int dqy1_dc = VP8Get(br, "global-header") ?
|
const int dqy1_dc = VP8Get(br, "global-header")
|
||||||
VP8GetSignedValue(br, 4, "global-header") : 0;
|
? VP8GetSignedValue(br, 4, "global-header")
|
||||||
const int dqy2_dc = VP8Get(br, "global-header") ?
|
: 0;
|
||||||
VP8GetSignedValue(br, 4, "global-header") : 0;
|
const int dqy2_dc = VP8Get(br, "global-header")
|
||||||
const int dqy2_ac = VP8Get(br, "global-header") ?
|
? VP8GetSignedValue(br, 4, "global-header")
|
||||||
VP8GetSignedValue(br, 4, "global-header") : 0;
|
: 0;
|
||||||
const int dquv_dc = VP8Get(br, "global-header") ?
|
const int dqy2_ac = VP8Get(br, "global-header")
|
||||||
VP8GetSignedValue(br, 4, "global-header") : 0;
|
? VP8GetSignedValue(br, 4, "global-header")
|
||||||
const int dquv_ac = VP8Get(br, "global-header") ?
|
: 0;
|
||||||
VP8GetSignedValue(br, 4, "global-header") : 0;
|
const int dquv_dc = VP8Get(br, "global-header")
|
||||||
|
? VP8GetSignedValue(br, 4, "global-header")
|
||||||
|
: 0;
|
||||||
|
const int dquv_ac = VP8Get(br, "global-header")
|
||||||
|
? VP8GetSignedValue(br, 4, "global-header")
|
||||||
|
: 0;
|
||||||
|
|
||||||
const VP8SegmentHeader* const hdr = &dec->segment_hdr;
|
const VP8SegmentHeader* const hdr = &dec->segment_hdr;
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -14,16 +14,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "src/dec/common_dec.h"
|
#include "src/dec/common_dec.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dec/vp8_dec.h"
|
#include "src/dec/vp8_dec.h"
|
||||||
#include "src/dec/vp8i_dec.h"
|
#include "src/dec/vp8i_dec.h"
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/utils/bit_reader_inl_utils.h"
|
#include "src/utils/bit_reader_inl_utils.h"
|
||||||
#include "src/utils/bit_reader_utils.h"
|
#include "src/utils/bit_reader_utils.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
#if !defined(USE_GENERIC_TREE)
|
#if !defined(USE_GENERIC_TREE)
|
||||||
#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 && \
|
#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 && !defined(__wasm__)
|
||||||
!defined(__wasm__)
|
|
||||||
// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
|
// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
|
||||||
#define USE_GENERIC_TREE 1 // ALTERNATE_CODE
|
#define USE_GENERIC_TREE 1 // ALTERNATE_CODE
|
||||||
#else
|
#else
|
||||||
@@ -33,269 +32,227 @@
|
|||||||
|
|
||||||
#if (USE_GENERIC_TREE == 1)
|
#if (USE_GENERIC_TREE == 1)
|
||||||
static const int8_t kYModesIntra4[18] = {
|
static const int8_t kYModesIntra4[18] = {
|
||||||
-B_DC_PRED, 1,
|
-B_DC_PRED, 1, -B_TM_PRED, 2, -B_VE_PRED, 3,
|
||||||
-B_TM_PRED, 2,
|
4, 6, -B_HE_PRED, 5, -B_RD_PRED, -B_VR_PRED,
|
||||||
-B_VE_PRED, 3,
|
-B_LD_PRED, 7, -B_VL_PRED, 8, -B_HD_PRED, -B_HU_PRED};
|
||||||
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
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Default probabilities
|
// Default probabilities
|
||||||
|
|
||||||
// Paragraph 13.5
|
// Paragraph 13.5
|
||||||
static const uint8_t
|
static const uint8_t CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
|
||||||
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},
|
||||||
{ 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},
|
||||||
},
|
},
|
||||||
{ { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
|
{
|
||||||
{ 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
|
{1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
|
||||||
{ 106, 126, 227, 252, 214, 209, 255, 255, 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, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
|
{{1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
|
||||||
{ 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
|
{170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
|
||||||
{ 78, 134, 202, 247, 198, 180, 255, 219, 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},
|
||||||
{ { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
|
{207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
|
||||||
{ 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
|
{102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128}},
|
||||||
{ 77, 110, 216, 255, 236, 230, 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},
|
||||||
{ { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
|
{80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128}},
|
||||||
{ 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
|
{{1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||||
{ 37, 116, 196, 243, 228, 255, 255, 255, 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}}},
|
||||||
{ { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
|
{{{198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
|
||||||
{ 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
|
{131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
|
||||||
{ 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
|
{68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128}},
|
||||||
},
|
{{1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
|
||||||
{ { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
|
{184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
|
||||||
{ 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
|
{81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128}},
|
||||||
{ 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
|
{{1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
|
||||||
},
|
{99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
|
||||||
{ { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
|
{23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128}},
|
||||||
{ 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
|
{{1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
|
||||||
{ 255, 128, 128, 128, 128, 128, 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},
|
||||||
{ { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 },
|
{94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
|
||||||
{ 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 },
|
{22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128}},
|
||||||
{ 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
|
{{1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
|
||||||
},
|
{124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
|
||||||
{ { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
|
{35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128}},
|
||||||
{ 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
|
{{1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
|
||||||
{ 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
|
{121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
|
||||||
},
|
{45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128}},
|
||||||
{ { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
|
{{1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
|
||||||
{ 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
|
{203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||||
{ 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
|
{137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128}}},
|
||||||
},
|
{{{253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
|
||||||
{ { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
|
{175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
|
||||||
{ 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
|
{73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128}},
|
||||||
{ 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
|
{{1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
|
||||||
},
|
{239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
|
||||||
{ { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
|
{155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128}},
|
||||||
{ 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
|
{{1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
|
||||||
{ 22, 100, 174, 245, 186, 161, 255, 199, 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, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
|
{{1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||||
{ 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
|
{223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
|
||||||
{ 35, 77, 181, 251, 193, 211, 255, 205, 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},
|
||||||
{ { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
|
{190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
|
||||||
{ 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
|
{149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}},
|
||||||
{ 45, 99, 188, 251, 195, 217, 255, 224, 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},
|
||||||
{ { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
|
{240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128}},
|
||||||
{ 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
|
{{1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||||
{ 137, 1, 177, 255, 224, 255, 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},
|
||||||
{ { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
|
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||||
{ 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
|
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}}},
|
||||||
{ 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
|
{{{202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
|
||||||
},
|
{126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
|
||||||
{ { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
|
{61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128}},
|
||||||
{ 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
|
{{1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
|
||||||
{ 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
|
{166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
|
||||||
},
|
{39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128}},
|
||||||
{ { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
|
{{1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
|
||||||
{ 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
|
{124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
|
||||||
{ 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
|
{24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128}},
|
||||||
},
|
{{1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
|
||||||
{ { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
|
{149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
|
||||||
{ 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
|
{28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128}},
|
||||||
{ 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
|
{{1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
|
||||||
},
|
{123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
|
||||||
{ { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
|
{20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128}},
|
||||||
{ 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
|
{{1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
|
||||||
{ 149, 1, 255, 128, 128, 128, 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, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
|
{{1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
|
||||||
{ 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
|
{141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
|
||||||
{ 240, 128, 255, 128, 128, 128, 128, 128, 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},
|
||||||
{ { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
|
{244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||||
{ 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
|
{238, 1, 255, 128, 128, 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
|
// Paragraph 11.5
|
||||||
static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
|
static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
|
||||||
{ { 231, 120, 48, 89, 115, 113, 120, 152, 112 },
|
{{231, 120, 48, 89, 115, 113, 120, 152, 112},
|
||||||
{ 152, 179, 64, 126, 170, 118, 46, 70, 95 },
|
{152, 179, 64, 126, 170, 118, 46, 70, 95},
|
||||||
{ 175, 69, 143, 80, 85, 82, 72, 155, 103 },
|
{175, 69, 143, 80, 85, 82, 72, 155, 103},
|
||||||
{ 56, 58, 10, 171, 218, 189, 17, 13, 152 },
|
{56, 58, 10, 171, 218, 189, 17, 13, 152},
|
||||||
{ 114, 26, 17, 163, 44, 195, 21, 10, 173 },
|
{114, 26, 17, 163, 44, 195, 21, 10, 173},
|
||||||
{ 121, 24, 80, 195, 26, 62, 44, 64, 85 },
|
{121, 24, 80, 195, 26, 62, 44, 64, 85},
|
||||||
{ 144, 71, 10, 38, 171, 213, 144, 34, 26 },
|
{144, 71, 10, 38, 171, 213, 144, 34, 26},
|
||||||
{ 170, 46, 55, 19, 136, 160, 33, 206, 71 },
|
{170, 46, 55, 19, 136, 160, 33, 206, 71},
|
||||||
{ 63, 20, 8, 114, 114, 208, 12, 9, 226 },
|
{63, 20, 8, 114, 114, 208, 12, 9, 226},
|
||||||
{ 81, 40, 11, 96, 182, 84, 29, 16, 36 } },
|
{81, 40, 11, 96, 182, 84, 29, 16, 36}},
|
||||||
{ { 134, 183, 89, 137, 98, 101, 106, 165, 148 },
|
{{134, 183, 89, 137, 98, 101, 106, 165, 148},
|
||||||
{ 72, 187, 100, 130, 157, 111, 32, 75, 80 },
|
{72, 187, 100, 130, 157, 111, 32, 75, 80},
|
||||||
{ 66, 102, 167, 99, 74, 62, 40, 234, 128 },
|
{66, 102, 167, 99, 74, 62, 40, 234, 128},
|
||||||
{ 41, 53, 9, 178, 241, 141, 26, 8, 107 },
|
{41, 53, 9, 178, 241, 141, 26, 8, 107},
|
||||||
{ 74, 43, 26, 146, 73, 166, 49, 23, 157 },
|
{74, 43, 26, 146, 73, 166, 49, 23, 157},
|
||||||
{ 65, 38, 105, 160, 51, 52, 31, 115, 128 },
|
{65, 38, 105, 160, 51, 52, 31, 115, 128},
|
||||||
{ 104, 79, 12, 27, 217, 255, 87, 17, 7 },
|
{104, 79, 12, 27, 217, 255, 87, 17, 7},
|
||||||
{ 87, 68, 71, 44, 114, 51, 15, 186, 23 },
|
{87, 68, 71, 44, 114, 51, 15, 186, 23},
|
||||||
{ 47, 41, 14, 110, 182, 183, 21, 17, 194 },
|
{47, 41, 14, 110, 182, 183, 21, 17, 194},
|
||||||
{ 66, 45, 25, 102, 197, 189, 23, 18, 22 } },
|
{66, 45, 25, 102, 197, 189, 23, 18, 22}},
|
||||||
{ { 88, 88, 147, 150, 42, 46, 45, 196, 205 },
|
{{88, 88, 147, 150, 42, 46, 45, 196, 205},
|
||||||
{ 43, 97, 183, 117, 85, 38, 35, 179, 61 },
|
{43, 97, 183, 117, 85, 38, 35, 179, 61},
|
||||||
{ 39, 53, 200, 87, 26, 21, 43, 232, 171 },
|
{39, 53, 200, 87, 26, 21, 43, 232, 171},
|
||||||
{ 56, 34, 51, 104, 114, 102, 29, 93, 77 },
|
{56, 34, 51, 104, 114, 102, 29, 93, 77},
|
||||||
{ 39, 28, 85, 171, 58, 165, 90, 98, 64 },
|
{39, 28, 85, 171, 58, 165, 90, 98, 64},
|
||||||
{ 34, 22, 116, 206, 23, 34, 43, 166, 73 },
|
{34, 22, 116, 206, 23, 34, 43, 166, 73},
|
||||||
{ 107, 54, 32, 26, 51, 1, 81, 43, 31 },
|
{107, 54, 32, 26, 51, 1, 81, 43, 31},
|
||||||
{ 68, 25, 106, 22, 64, 171, 36, 225, 114 },
|
{68, 25, 106, 22, 64, 171, 36, 225, 114},
|
||||||
{ 34, 19, 21, 102, 132, 188, 16, 76, 124 },
|
{34, 19, 21, 102, 132, 188, 16, 76, 124},
|
||||||
{ 62, 18, 78, 95, 85, 57, 50, 48, 51 } },
|
{62, 18, 78, 95, 85, 57, 50, 48, 51}},
|
||||||
{ { 193, 101, 35, 159, 215, 111, 89, 46, 111 },
|
{{193, 101, 35, 159, 215, 111, 89, 46, 111},
|
||||||
{ 60, 148, 31, 172, 219, 228, 21, 18, 111 },
|
{60, 148, 31, 172, 219, 228, 21, 18, 111},
|
||||||
{ 112, 113, 77, 85, 179, 255, 38, 120, 114 },
|
{112, 113, 77, 85, 179, 255, 38, 120, 114},
|
||||||
{ 40, 42, 1, 196, 245, 209, 10, 25, 109 },
|
{40, 42, 1, 196, 245, 209, 10, 25, 109},
|
||||||
{ 88, 43, 29, 140, 166, 213, 37, 43, 154 },
|
{88, 43, 29, 140, 166, 213, 37, 43, 154},
|
||||||
{ 61, 63, 30, 155, 67, 45, 68, 1, 209 },
|
{61, 63, 30, 155, 67, 45, 68, 1, 209},
|
||||||
{ 100, 80, 8, 43, 154, 1, 51, 26, 71 },
|
{100, 80, 8, 43, 154, 1, 51, 26, 71},
|
||||||
{ 142, 78, 78, 16, 255, 128, 34, 197, 171 },
|
{142, 78, 78, 16, 255, 128, 34, 197, 171},
|
||||||
{ 41, 40, 5, 102, 211, 183, 4, 1, 221 },
|
{41, 40, 5, 102, 211, 183, 4, 1, 221},
|
||||||
{ 51, 50, 17, 168, 209, 192, 23, 25, 82 } },
|
{51, 50, 17, 168, 209, 192, 23, 25, 82}},
|
||||||
{ { 138, 31, 36, 171, 27, 166, 38, 44, 229 },
|
{{138, 31, 36, 171, 27, 166, 38, 44, 229},
|
||||||
{ 67, 87, 58, 169, 82, 115, 26, 59, 179 },
|
{67, 87, 58, 169, 82, 115, 26, 59, 179},
|
||||||
{ 63, 59, 90, 180, 59, 166, 93, 73, 154 },
|
{63, 59, 90, 180, 59, 166, 93, 73, 154},
|
||||||
{ 40, 40, 21, 116, 143, 209, 34, 39, 175 },
|
{40, 40, 21, 116, 143, 209, 34, 39, 175},
|
||||||
{ 47, 15, 16, 183, 34, 223, 49, 45, 183 },
|
{47, 15, 16, 183, 34, 223, 49, 45, 183},
|
||||||
{ 46, 17, 33, 183, 6, 98, 15, 32, 183 },
|
{46, 17, 33, 183, 6, 98, 15, 32, 183},
|
||||||
{ 57, 46, 22, 24, 128, 1, 54, 17, 37 },
|
{57, 46, 22, 24, 128, 1, 54, 17, 37},
|
||||||
{ 65, 32, 73, 115, 28, 128, 23, 128, 205 },
|
{65, 32, 73, 115, 28, 128, 23, 128, 205},
|
||||||
{ 40, 3, 9, 115, 51, 192, 18, 6, 223 },
|
{40, 3, 9, 115, 51, 192, 18, 6, 223},
|
||||||
{ 87, 37, 9, 115, 59, 77, 64, 21, 47 } },
|
{87, 37, 9, 115, 59, 77, 64, 21, 47}},
|
||||||
{ { 104, 55, 44, 218, 9, 54, 53, 130, 226 },
|
{{104, 55, 44, 218, 9, 54, 53, 130, 226},
|
||||||
{ 64, 90, 70, 205, 40, 41, 23, 26, 57 },
|
{64, 90, 70, 205, 40, 41, 23, 26, 57},
|
||||||
{ 54, 57, 112, 184, 5, 41, 38, 166, 213 },
|
{54, 57, 112, 184, 5, 41, 38, 166, 213},
|
||||||
{ 30, 34, 26, 133, 152, 116, 10, 32, 134 },
|
{30, 34, 26, 133, 152, 116, 10, 32, 134},
|
||||||
{ 39, 19, 53, 221, 26, 114, 32, 73, 255 },
|
{39, 19, 53, 221, 26, 114, 32, 73, 255},
|
||||||
{ 31, 9, 65, 234, 2, 15, 1, 118, 73 },
|
{31, 9, 65, 234, 2, 15, 1, 118, 73},
|
||||||
{ 75, 32, 12, 51, 192, 255, 160, 43, 51 },
|
{75, 32, 12, 51, 192, 255, 160, 43, 51},
|
||||||
{ 88, 31, 35, 67, 102, 85, 55, 186, 85 },
|
{88, 31, 35, 67, 102, 85, 55, 186, 85},
|
||||||
{ 56, 21, 23, 111, 59, 205, 45, 37, 192 },
|
{56, 21, 23, 111, 59, 205, 45, 37, 192},
|
||||||
{ 55, 38, 70, 124, 73, 102, 1, 34, 98 } },
|
{55, 38, 70, 124, 73, 102, 1, 34, 98}},
|
||||||
{ { 125, 98, 42, 88, 104, 85, 117, 175, 82 },
|
{{125, 98, 42, 88, 104, 85, 117, 175, 82},
|
||||||
{ 95, 84, 53, 89, 128, 100, 113, 101, 45 },
|
{95, 84, 53, 89, 128, 100, 113, 101, 45},
|
||||||
{ 75, 79, 123, 47, 51, 128, 81, 171, 1 },
|
{75, 79, 123, 47, 51, 128, 81, 171, 1},
|
||||||
{ 57, 17, 5, 71, 102, 57, 53, 41, 49 },
|
{57, 17, 5, 71, 102, 57, 53, 41, 49},
|
||||||
{ 38, 33, 13, 121, 57, 73, 26, 1, 85 },
|
{38, 33, 13, 121, 57, 73, 26, 1, 85},
|
||||||
{ 41, 10, 67, 138, 77, 110, 90, 47, 114 },
|
{41, 10, 67, 138, 77, 110, 90, 47, 114},
|
||||||
{ 115, 21, 2, 10, 102, 255, 166, 23, 6 },
|
{115, 21, 2, 10, 102, 255, 166, 23, 6},
|
||||||
{ 101, 29, 16, 10, 85, 128, 101, 196, 26 },
|
{101, 29, 16, 10, 85, 128, 101, 196, 26},
|
||||||
{ 57, 18, 10, 102, 102, 213, 34, 20, 43 },
|
{57, 18, 10, 102, 102, 213, 34, 20, 43},
|
||||||
{ 117, 20, 15, 36, 163, 128, 68, 1, 26 } },
|
{117, 20, 15, 36, 163, 128, 68, 1, 26}},
|
||||||
{ { 102, 61, 71, 37, 34, 53, 31, 243, 192 },
|
{{102, 61, 71, 37, 34, 53, 31, 243, 192},
|
||||||
{ 69, 60, 71, 38, 73, 119, 28, 222, 37 },
|
{69, 60, 71, 38, 73, 119, 28, 222, 37},
|
||||||
{ 68, 45, 128, 34, 1, 47, 11, 245, 171 },
|
{68, 45, 128, 34, 1, 47, 11, 245, 171},
|
||||||
{ 62, 17, 19, 70, 146, 85, 55, 62, 70 },
|
{62, 17, 19, 70, 146, 85, 55, 62, 70},
|
||||||
{ 37, 43, 37, 154, 100, 163, 85, 160, 1 },
|
{37, 43, 37, 154, 100, 163, 85, 160, 1},
|
||||||
{ 63, 9, 92, 136, 28, 64, 32, 201, 85 },
|
{63, 9, 92, 136, 28, 64, 32, 201, 85},
|
||||||
{ 75, 15, 9, 9, 64, 255, 184, 119, 16 },
|
{75, 15, 9, 9, 64, 255, 184, 119, 16},
|
||||||
{ 86, 6, 28, 5, 64, 255, 25, 248, 1 },
|
{86, 6, 28, 5, 64, 255, 25, 248, 1},
|
||||||
{ 56, 8, 17, 132, 137, 255, 55, 116, 128 },
|
{56, 8, 17, 132, 137, 255, 55, 116, 128},
|
||||||
{ 58, 15, 20, 82, 135, 57, 26, 121, 40 } },
|
{58, 15, 20, 82, 135, 57, 26, 121, 40}},
|
||||||
{ { 164, 50, 31, 137, 154, 133, 25, 35, 218 },
|
{{164, 50, 31, 137, 154, 133, 25, 35, 218},
|
||||||
{ 51, 103, 44, 131, 131, 123, 31, 6, 158 },
|
{51, 103, 44, 131, 131, 123, 31, 6, 158},
|
||||||
{ 86, 40, 64, 135, 148, 224, 45, 183, 128 },
|
{86, 40, 64, 135, 148, 224, 45, 183, 128},
|
||||||
{ 22, 26, 17, 131, 240, 154, 14, 1, 209 },
|
{22, 26, 17, 131, 240, 154, 14, 1, 209},
|
||||||
{ 45, 16, 21, 91, 64, 222, 7, 1, 197 },
|
{45, 16, 21, 91, 64, 222, 7, 1, 197},
|
||||||
{ 56, 21, 39, 155, 60, 138, 23, 102, 213 },
|
{56, 21, 39, 155, 60, 138, 23, 102, 213},
|
||||||
{ 83, 12, 13, 54, 192, 255, 68, 47, 28 },
|
{83, 12, 13, 54, 192, 255, 68, 47, 28},
|
||||||
{ 85, 26, 85, 85, 128, 128, 32, 146, 171 },
|
{85, 26, 85, 85, 128, 128, 32, 146, 171},
|
||||||
{ 18, 11, 7, 63, 144, 171, 4, 4, 246 },
|
{18, 11, 7, 63, 144, 171, 4, 4, 246},
|
||||||
{ 35, 27, 10, 146, 174, 171, 12, 26, 128 } },
|
{35, 27, 10, 146, 174, 171, 12, 26, 128}},
|
||||||
{ { 190, 80, 35, 99, 180, 80, 126, 54, 45 },
|
{{190, 80, 35, 99, 180, 80, 126, 54, 45},
|
||||||
{ 85, 126, 47, 87, 176, 51, 41, 20, 32 },
|
{85, 126, 47, 87, 176, 51, 41, 20, 32},
|
||||||
{ 101, 75, 128, 139, 118, 146, 116, 128, 85 },
|
{101, 75, 128, 139, 118, 146, 116, 128, 85},
|
||||||
{ 56, 41, 15, 176, 236, 85, 37, 9, 62 },
|
{56, 41, 15, 176, 236, 85, 37, 9, 62},
|
||||||
{ 71, 30, 17, 119, 118, 255, 17, 18, 138 },
|
{71, 30, 17, 119, 118, 255, 17, 18, 138},
|
||||||
{ 101, 38, 60, 138, 55, 70, 43, 26, 142 },
|
{101, 38, 60, 138, 55, 70, 43, 26, 142},
|
||||||
{ 146, 36, 19, 30, 171, 255, 97, 27, 20 },
|
{146, 36, 19, 30, 171, 255, 97, 27, 20},
|
||||||
{ 138, 45, 61, 62, 219, 1, 81, 188, 64 },
|
{138, 45, 61, 62, 219, 1, 81, 188, 64},
|
||||||
{ 32, 41, 20, 117, 151, 142, 20, 21, 163 },
|
{32, 41, 20, 117, 151, 142, 20, 21, 163},
|
||||||
{ 112, 19, 12, 61, 195, 128, 48, 4, 24 } }
|
{112, 19, 12, 61, 195, 128, 48, 4, 24}}};
|
||||||
};
|
|
||||||
|
|
||||||
void VP8ResetProba(VP8Proba* const proba) {
|
void VP8ResetProba(VP8Proba* const proba) {
|
||||||
memset(proba->segments, 255u, sizeof(proba->segments));
|
memset(proba->segments, 255u, sizeof(proba->segments));
|
||||||
// proba->bands[][] is initialized later
|
// proba->bands[][] is initialized later
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParseIntraMode(VP8BitReader* const br,
|
static void ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec,
|
||||||
VP8Decoder* const dec, int mb_x) {
|
int mb_x) {
|
||||||
uint8_t* const top = dec->intra_t + 4 * mb_x;
|
uint8_t* const top = dec->intra_t + 4 * mb_x;
|
||||||
uint8_t* const left = dec->intra_l;
|
uint8_t* const left = dec->intra_l;
|
||||||
VP8MBData* const block = dec->mb_data + mb_x;
|
VP8MBData* const block = dec->mb_data + mb_x;
|
||||||
@@ -304,7 +261,8 @@ static void ParseIntraMode(VP8BitReader* const br,
|
|||||||
// to decode more than 1 keyframe.
|
// to decode more than 1 keyframe.
|
||||||
if (dec->segment_hdr.update_map) {
|
if (dec->segment_hdr.update_map) {
|
||||||
// Hardcoded tree parsing
|
// Hardcoded tree parsing
|
||||||
block->segment = !VP8GetBit(br, dec->proba.segments[0], "segments")
|
block->segment =
|
||||||
|
!VP8GetBit(br, dec->proba.segments[0], "segments")
|
||||||
? VP8GetBit(br, dec->proba.segments[1], "segments")
|
? VP8GetBit(br, dec->proba.segments[1], "segments")
|
||||||
: VP8GetBit(br, dec->proba.segments[2], "segments") + 2;
|
: VP8GetBit(br, dec->proba.segments[2], "segments") + 2;
|
||||||
} else {
|
} else {
|
||||||
@@ -316,9 +274,9 @@ static void ParseIntraMode(VP8BitReader* const br,
|
|||||||
if (!block->is_i4x4) {
|
if (!block->is_i4x4) {
|
||||||
// Hardcoded 16x16 intra-mode decision tree.
|
// Hardcoded 16x16 intra-mode decision tree.
|
||||||
const int ymode =
|
const int ymode =
|
||||||
VP8GetBit(br, 156, "pred-modes") ?
|
VP8GetBit(br, 156, "pred-modes")
|
||||||
(VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) :
|
? (VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED)
|
||||||
(VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED);
|
: (VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED);
|
||||||
block->imodes[0] = ymode;
|
block->imodes[0] = ymode;
|
||||||
memset(top, ymode, 4 * sizeof(*top));
|
memset(top, ymode, 4 * sizeof(*top));
|
||||||
memset(left, ymode, 4 * sizeof(*left));
|
memset(left, ymode, 4 * sizeof(*left));
|
||||||
@@ -339,18 +297,22 @@ static void ParseIntraMode(VP8BitReader* const br,
|
|||||||
ymode = -i;
|
ymode = -i;
|
||||||
#else
|
#else
|
||||||
// Hardcoded tree parsing
|
// Hardcoded tree parsing
|
||||||
ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED :
|
ymode =
|
||||||
!VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED :
|
!VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED
|
||||||
!VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED :
|
: !VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED
|
||||||
!VP8GetBit(br, prob[3], "pred-modes") ?
|
: !VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED
|
||||||
(!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED :
|
: !VP8GetBit(br, prob[3], "pred-modes")
|
||||||
(!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED
|
? (!VP8GetBit(br, prob[4], "pred-modes")
|
||||||
: B_VR_PRED)) :
|
? B_HE_PRED
|
||||||
(!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED :
|
: (!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED
|
||||||
(!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED :
|
: B_VR_PRED))
|
||||||
(!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED
|
: (!VP8GetBit(br, prob[6], "pred-modes")
|
||||||
: B_HU_PRED))
|
? B_LD_PRED
|
||||||
);
|
: (!VP8GetBit(br, prob[7], "pred-modes")
|
||||||
|
? B_VL_PRED
|
||||||
|
: (!VP8GetBit(br, prob[8], "pred-modes")
|
||||||
|
? B_HD_PRED
|
||||||
|
: B_HU_PRED)));
|
||||||
#endif // USE_GENERIC_TREE
|
#endif // USE_GENERIC_TREE
|
||||||
top[x] = ymode;
|
top[x] = ymode;
|
||||||
}
|
}
|
||||||
@@ -362,7 +324,8 @@ static void ParseIntraMode(VP8BitReader* const br,
|
|||||||
// Hardcoded UVMode decision tree
|
// Hardcoded UVMode decision tree
|
||||||
block->uvmode = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED
|
block->uvmode = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED
|
||||||
: !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED
|
: !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED
|
||||||
: VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED;
|
: VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED
|
||||||
|
: H_PRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
|
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
|
||||||
@@ -378,139 +341,102 @@ int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
|
|||||||
|
|
||||||
static const uint8_t
|
static const uint8_t
|
||||||
CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
|
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 },
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 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},
|
||||||
{ { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{223, 241, 252, 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}},
|
||||||
{ 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},
|
||||||
{ { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 253, 255, 255, 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, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 254, 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},
|
||||||
{ { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 255, 255, 255, 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},
|
||||||
{ { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 254, 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, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 },
|
{{{217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 },
|
{225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
|
||||||
{ 254, 255, 255, 255, 255, 255, 255, 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},
|
||||||
{ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 255, 255, 255, 255, 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}},
|
||||||
{ { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 },
|
{247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 234, 250, 241, 250, 253, 255, 253, 254, 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},
|
||||||
{ { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 238, 253, 254, 254, 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, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 255, 255, 255, 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, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 255, 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, 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},
|
||||||
{ { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{251, 251, 243, 253, 254, 255, 254, 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},
|
||||||
},
|
{236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 255, 255, 255, 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, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 250, 255, 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 }
|
{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 },
|
{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}},
|
||||||
{ { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 },
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 251, 251, 243, 253, 254, 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, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}}},
|
||||||
{ 251, 253, 253, 254, 254, 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},
|
||||||
{ { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{{255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 254, 255, 255, 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},
|
||||||
{ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
|
{253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}},
|
||||||
{ 255, 255, 255, 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, 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, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
{ 255, 255, 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, 255, 255, 255, 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 },
|
{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}},
|
||||||
},
|
{{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 },
|
{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
|
// Paragraph 9.9
|
||||||
|
|
||||||
@@ -527,9 +453,9 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
|
|||||||
for (c = 0; c < NUM_CTX; ++c) {
|
for (c = 0; c < NUM_CTX; ++c) {
|
||||||
for (p = 0; p < NUM_PROBAS; ++p) {
|
for (p = 0; p < NUM_PROBAS; ++p) {
|
||||||
const int v =
|
const int v =
|
||||||
VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ?
|
VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header")
|
||||||
VP8GetValue(br, 8, "global-header") :
|
? VP8GetValue(br, 8, "global-header")
|
||||||
CoeffsProba0[t][b][c][p];
|
: CoeffsProba0[t][b][c][p];
|
||||||
proba->bands[t][b].probas[c][p] = v;
|
proba->bands[t][b].probas[c][p] = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,14 @@
|
|||||||
//
|
//
|
||||||
// Author: Skal (pascal.massimino@gmail.com)
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#include "src/dec/vp8_dec.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "src/dec/alphai_dec.h"
|
#include "src/dec/alphai_dec.h"
|
||||||
#include "src/dec/common_dec.h"
|
#include "src/dec/common_dec.h"
|
||||||
#include "src/dec/vp8_dec.h"
|
|
||||||
#include "src/dec/vp8i_dec.h"
|
#include "src/dec/vp8i_dec.h"
|
||||||
#include "src/dec/vp8li_dec.h"
|
#include "src/dec/vp8li_dec.h"
|
||||||
#include "src/dec/webpi_dec.h"
|
#include "src/dec/webpi_dec.h"
|
||||||
@@ -41,8 +42,8 @@ int WebPGetDecoderVersion(void) {
|
|||||||
// Signature and pointer-to-function for GetCoeffs() variants below.
|
// Signature and pointer-to-function for GetCoeffs() variants below.
|
||||||
|
|
||||||
typedef int (*GetCoeffsFunc)(VP8BitReader* const br,
|
typedef int (*GetCoeffsFunc)(VP8BitReader* const br,
|
||||||
const VP8BandProbas* const prob[],
|
const VP8BandProbas* const prob[], int ctx,
|
||||||
int ctx, const quant_t dq, int n, int16_t* out);
|
const quant_t dq, int n, int16_t* out);
|
||||||
static volatile GetCoeffsFunc GetCoeffs = NULL;
|
static volatile GetCoeffsFunc GetCoeffs = NULL;
|
||||||
|
|
||||||
static void InitGetCoeffs(void);
|
static void InitGetCoeffs(void);
|
||||||
@@ -95,8 +96,8 @@ void VP8Delete(VP8Decoder* const dec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8SetError(VP8Decoder* const dec,
|
int VP8SetError(VP8Decoder* const dec, VP8StatusCode error,
|
||||||
VP8StatusCode error, const char* const msg) {
|
const char* const msg) {
|
||||||
// VP8_STATUS_SUSPENDED is only meaningful in incremental decoding.
|
// VP8_STATUS_SUSPENDED is only meaningful in incremental decoding.
|
||||||
assert(dec->incremental || error != VP8_STATUS_SUSPENDED);
|
assert(dec->incremental || error != VP8_STATUS_SUSPENDED);
|
||||||
// The oldest error reported takes precedence over the new one.
|
// The oldest error reported takes precedence over the new one.
|
||||||
@@ -111,8 +112,8 @@ int VP8SetError(VP8Decoder* const dec,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int VP8CheckSignature(const uint8_t* const data, size_t data_size) {
|
int VP8CheckSignature(const uint8_t* const data, size_t data_size) {
|
||||||
return (data_size >= 3 &&
|
return (data_size >= 3 && data[0] == 0x9d && data[1] == 0x01 &&
|
||||||
data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a);
|
data[2] == 0x2a);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
|
int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
|
||||||
@@ -170,8 +171,8 @@ static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Paragraph 9.3
|
// Paragraph 9.3
|
||||||
static int ParseSegmentHeader(VP8BitReader* br,
|
static int ParseSegmentHeader(VP8BitReader* br, VP8SegmentHeader* hdr,
|
||||||
VP8SegmentHeader* hdr, VP8Proba* proba) {
|
VP8Proba* proba) {
|
||||||
assert(br != NULL);
|
assert(br != NULL);
|
||||||
assert(hdr != NULL);
|
assert(hdr != NULL);
|
||||||
hdr->use_segment = VP8Get(br, "global-header");
|
hdr->use_segment = VP8Get(br, "global-header");
|
||||||
@@ -181,19 +182,23 @@ static int ParseSegmentHeader(VP8BitReader* br,
|
|||||||
int s;
|
int s;
|
||||||
hdr->absolute_delta = VP8Get(br, "global-header");
|
hdr->absolute_delta = VP8Get(br, "global-header");
|
||||||
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
|
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
|
||||||
hdr->quantizer[s] = VP8Get(br, "global-header") ?
|
hdr->quantizer[s] = VP8Get(br, "global-header")
|
||||||
VP8GetSignedValue(br, 7, "global-header") : 0;
|
? VP8GetSignedValue(br, 7, "global-header")
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
|
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
|
||||||
hdr->filter_strength[s] = VP8Get(br, "global-header") ?
|
hdr->filter_strength[s] =
|
||||||
VP8GetSignedValue(br, 6, "global-header") : 0;
|
VP8Get(br, "global-header")
|
||||||
|
? VP8GetSignedValue(br, 6, "global-header")
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hdr->update_map) {
|
if (hdr->update_map) {
|
||||||
int s;
|
int s;
|
||||||
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
|
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
|
||||||
proba->segments[s] = VP8Get(br, "global-header") ?
|
proba->segments[s] = VP8Get(br, "global-header")
|
||||||
VP8GetValue(br, 8, "global-header") : 255u;
|
? VP8GetValue(br, 8, "global-header")
|
||||||
|
: 255u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -211,8 +216,8 @@ static int ParseSegmentHeader(VP8BitReader* br,
|
|||||||
// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA
|
// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA
|
||||||
// is returned, and this is an unrecoverable error.
|
// is returned, and this is an unrecoverable error.
|
||||||
// If the partitions were positioned ok, VP8_STATUS_OK is returned.
|
// If the partitions were positioned ok, VP8_STATUS_OK is returned.
|
||||||
static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
|
static VP8StatusCode ParsePartitions(VP8Decoder* const dec, const uint8_t* buf,
|
||||||
const uint8_t* buf, size_t size) {
|
size_t size) {
|
||||||
VP8BitReader* const br = &dec->br;
|
VP8BitReader* const br = &dec->br;
|
||||||
const uint8_t* sz = buf;
|
const uint8_t* sz = buf;
|
||||||
const uint8_t* buf_end = buf + size;
|
const uint8_t* buf_end = buf + size;
|
||||||
@@ -290,8 +295,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
|
|||||||
buf = io->data;
|
buf = io->data;
|
||||||
buf_size = io->data_size;
|
buf_size = io->data_size;
|
||||||
if (buf_size < 4) {
|
if (buf_size < 4) {
|
||||||
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
|
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, "Truncated header.");
|
||||||
"Truncated header.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paragraph 9.1
|
// Paragraph 9.1
|
||||||
@@ -322,8 +326,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
|
|||||||
"cannot parse picture header");
|
"cannot parse picture header");
|
||||||
}
|
}
|
||||||
if (!VP8CheckSignature(buf, buf_size)) {
|
if (!VP8CheckSignature(buf, buf_size)) {
|
||||||
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
|
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, "Bad code word");
|
||||||
"Bad code word");
|
|
||||||
}
|
}
|
||||||
pic_hdr->width = ((buf[4] << 8) | buf[3]) & 0x3fff;
|
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->xscale = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2
|
||||||
@@ -360,8 +363,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
|
|||||||
// Check if we have all the partition #0 available, and initialize dec->br
|
// Check if we have all the partition #0 available, and initialize dec->br
|
||||||
// to read this partition (and this partition only).
|
// to read this partition (and this partition only).
|
||||||
if (frm_hdr->partition_length > buf_size) {
|
if (frm_hdr->partition_length > buf_size) {
|
||||||
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
|
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, "bad partition length");
|
||||||
"bad partition length");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
br = &dec->br;
|
br = &dec->br;
|
||||||
@@ -392,8 +394,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
|
|||||||
|
|
||||||
// Frame buffer marking
|
// Frame buffer marking
|
||||||
if (!frm_hdr->key_frame) {
|
if (!frm_hdr->key_frame) {
|
||||||
return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
|
return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, "Not a key frame.");
|
||||||
"Not a key frame.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8Get(br, "global-header"); // ignore the value of 'update_proba'
|
VP8Get(br, "global-header"); // ignore the value of 'update_proba'
|
||||||
@@ -408,15 +409,14 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Residual decoding (Paragraph 13.2 / 13.3)
|
// Residual decoding (Paragraph 13.2 / 13.3)
|
||||||
|
|
||||||
static const uint8_t kCat3[] = { 173, 148, 140, 0 };
|
static const uint8_t kCat3[] = {173, 148, 140, 0};
|
||||||
static const uint8_t kCat4[] = { 176, 155, 140, 135, 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 kCat5[] = {180, 157, 141, 134, 130, 0};
|
||||||
static const uint8_t kCat6[] =
|
static const uint8_t kCat6[] = {254, 254, 243, 230, 196, 177,
|
||||||
{ 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };
|
153, 140, 133, 130, 129, 0};
|
||||||
static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
|
static const uint8_t* const kCat3456[] = {kCat3, kCat4, kCat5, kCat6};
|
||||||
static const uint8_t kZigzag[16] = {
|
static const uint8_t kZigzag[16] = {0, 1, 4, 8, 5, 2, 3, 6,
|
||||||
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
|
9, 12, 13, 10, 7, 11, 14, 15};
|
||||||
};
|
|
||||||
|
|
||||||
// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2
|
// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2
|
||||||
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
|
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
|
||||||
@@ -452,8 +452,8 @@ static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
|
|||||||
|
|
||||||
// Returns the position of the last non-zero coeff plus one
|
// Returns the position of the last non-zero coeff plus one
|
||||||
static int GetCoeffsFast(VP8BitReader* const br,
|
static int GetCoeffsFast(VP8BitReader* const br,
|
||||||
const VP8BandProbas* const prob[],
|
const VP8BandProbas* const prob[], int ctx,
|
||||||
int ctx, const quant_t dq, int n, int16_t* out) {
|
const quant_t dq, int n, int16_t* out) {
|
||||||
const uint8_t* p = prob[n]->probas[ctx];
|
const uint8_t* p = prob[n]->probas[ctx];
|
||||||
for (; n < 16; ++n) {
|
for (; n < 16; ++n) {
|
||||||
if (!VP8GetBit(br, p[0], "coeffs")) {
|
if (!VP8GetBit(br, p[0], "coeffs")) {
|
||||||
@@ -482,8 +482,8 @@ static int GetCoeffsFast(VP8BitReader* const br,
|
|||||||
// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version
|
// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version
|
||||||
// of VP8GetBitAlt() targeting specific platforms.
|
// of VP8GetBitAlt() targeting specific platforms.
|
||||||
static int GetCoeffsAlt(VP8BitReader* const br,
|
static int GetCoeffsAlt(VP8BitReader* const br,
|
||||||
const VP8BandProbas* const prob[],
|
const VP8BandProbas* const prob[], int ctx,
|
||||||
int ctx, const quant_t dq, int n, int16_t* out) {
|
const quant_t dq, int n, int16_t* out) {
|
||||||
const uint8_t* p = prob[n]->probas[ctx];
|
const uint8_t* p = prob[n]->probas[ctx];
|
||||||
for (; n < 16; ++n) {
|
for (; n < 16; ++n) {
|
||||||
if (!VP8GetBitAlt(br, p[0], "coeffs")) {
|
if (!VP8GetBitAlt(br, p[0], "coeffs")) {
|
||||||
@@ -525,10 +525,10 @@ static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {
|
|||||||
return nz_coeffs;
|
return nz_coeffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ParseResiduals(VP8Decoder* const dec,
|
static int ParseResiduals(VP8Decoder* const dec, VP8MB* const mb,
|
||||||
VP8MB* const mb, VP8BitReader* const token_br) {
|
VP8BitReader* const token_br) {
|
||||||
const VP8BandProbas* (* const bands)[16 + 1] = dec->proba.bands_ptr;
|
const VP8BandProbas*(*const bands)[16 + 1] = dec->proba.bands_ptr;
|
||||||
const VP8BandProbas* const * ac_proba;
|
const VP8BandProbas* const* ac_proba;
|
||||||
VP8MBData* const block = dec->mb_data + dec->mb_x;
|
VP8MBData* const block = dec->mb_data + dec->mb_x;
|
||||||
const VP8QuantMatrix* const q = &dec->dqm[block->segment];
|
const VP8QuantMatrix* const q = &dec->dqm[block->segment];
|
||||||
int16_t* dst = block->coeffs;
|
int16_t* dst = block->coeffs;
|
||||||
@@ -542,7 +542,7 @@ static int ParseResiduals(VP8Decoder* const dec,
|
|||||||
|
|
||||||
memset(dst, 0, 384 * sizeof(*dst));
|
memset(dst, 0, 384 * sizeof(*dst));
|
||||||
if (!block->is_i4x4) { // parse DC
|
if (!block->is_i4x4) { // parse DC
|
||||||
int16_t dc[16] = { 0 };
|
int16_t dc[16] = {0};
|
||||||
const int ctx = mb->nz_dc + left_mb->nz_dc;
|
const int ctx = mb->nz_dc + left_mb->nz_dc;
|
||||||
const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat, 0, dc);
|
const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat, 0, dc);
|
||||||
mb->nz_dc = left_mb->nz_dc = (nz > 0);
|
mb->nz_dc = left_mb->nz_dc = (nz > 0);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ struct VP8Io {
|
|||||||
int mb_y; // position of the current rows (in pixels)
|
int mb_y; // position of the current rows (in pixels)
|
||||||
int mb_w; // number of columns in the sample
|
int mb_w; // number of columns in the sample
|
||||||
int mb_h; // number of rows in the sample
|
int mb_h; // number of rows in the sample
|
||||||
const uint8_t* y, *u, *v; // rows to copy (in yuv420 format)
|
const uint8_t *y, *u, *v; // rows to copy (in yuv420 format)
|
||||||
int y_stride; // row stride for luma
|
int y_stride; // row stride for luma
|
||||||
int uv_stride; // row stride for chroma
|
int uv_stride; // row stride for chroma
|
||||||
|
|
||||||
@@ -175,9 +175,10 @@ WEBP_EXTERN int VP8LCheckSignature(const uint8_t* const data, size_t size);
|
|||||||
// Validates the VP8L data-header and retrieves basic header information viz
|
// Validates the VP8L data-header and retrieves basic header information viz
|
||||||
// width, height and alpha. Returns 0 in case of formatting error.
|
// width, height and alpha. Returns 0 in case of formatting error.
|
||||||
// width/height/has_alpha can be passed NULL.
|
// width/height/has_alpha can be passed NULL.
|
||||||
WEBP_EXTERN int VP8LGetInfo(
|
WEBP_EXTERN int VP8LGetInfo(const uint8_t* data,
|
||||||
const uint8_t* data, size_t data_size, // data available so far
|
size_t data_size, // data available so far
|
||||||
int* const width, int* const height, int* const has_alpha);
|
int* const width, int* const height,
|
||||||
|
int* const has_alpha);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -274,8 +274,8 @@ struct VP8Decoder {
|
|||||||
// internal functions. Not public.
|
// internal functions. Not public.
|
||||||
|
|
||||||
// in vp8.c
|
// in vp8.c
|
||||||
int VP8SetError(VP8Decoder* const dec,
|
int VP8SetError(VP8Decoder* const dec, VP8StatusCode error,
|
||||||
VP8StatusCode error, const char* const msg);
|
const char* const msg);
|
||||||
|
|
||||||
// in tree.c
|
// in tree.c
|
||||||
void VP8ResetProba(VP8Proba* const proba);
|
void VP8ResetProba(VP8Proba* const proba);
|
||||||
@@ -299,8 +299,8 @@ WEBP_NODISCARD int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
|
|||||||
// Return the multi-threading method to use (0=off), depending
|
// Return the multi-threading method to use (0=off), depending
|
||||||
// on options and bitstream size. Only for lossy decoding.
|
// on options and bitstream size. Only for lossy decoding.
|
||||||
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
|
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
|
||||||
const WebPHeaderStructure* const headers,
|
const WebPHeaderStructure* const headers, int width,
|
||||||
int width, int height);
|
int height);
|
||||||
// Initialize dithering post-process if needed.
|
// Initialize dithering post-process if needed.
|
||||||
void VP8InitDithering(const WebPDecoderOptions* const options,
|
void VP8InitDithering(const WebPDecoderOptions* const options,
|
||||||
VP8Decoder* const dec);
|
VP8Decoder* const dec);
|
||||||
@@ -314,8 +314,8 @@ WEBP_NODISCARD int VP8DecodeMB(VP8Decoder* const dec,
|
|||||||
|
|
||||||
// in alpha.c
|
// in alpha.c
|
||||||
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||||
const VP8Io* const io,
|
const VP8Io* const io, int row,
|
||||||
int row, int num_rows);
|
int num_rows);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,8 @@
|
|||||||
|
|
||||||
static const int kCodeLengthLiterals = 16;
|
static const int kCodeLengthLiterals = 16;
|
||||||
static const int kCodeLengthRepeatCode = 16;
|
static const int kCodeLengthRepeatCode = 16;
|
||||||
static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 };
|
static const uint8_t kCodeLengthExtraBits[3] = {2, 3, 7};
|
||||||
static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
|
static const uint8_t kCodeLengthRepeatOffsets[3] = {3, 3, 11};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Five Huffman codes are used at each meta code:
|
// Five Huffman codes are used at each meta code:
|
||||||
@@ -47,44 +47,30 @@ static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
|
|||||||
// 3. red,
|
// 3. red,
|
||||||
// 4. blue, and,
|
// 4. blue, and,
|
||||||
// 5. distance prefix codes.
|
// 5. distance prefix codes.
|
||||||
typedef enum {
|
typedef enum { GREEN = 0, RED = 1, BLUE = 2, ALPHA = 3, DIST = 4 } HuffIndex;
|
||||||
GREEN = 0,
|
|
||||||
RED = 1,
|
|
||||||
BLUE = 2,
|
|
||||||
ALPHA = 3,
|
|
||||||
DIST = 4
|
|
||||||
} HuffIndex;
|
|
||||||
|
|
||||||
static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
|
static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
|
||||||
NUM_LITERAL_CODES + NUM_LENGTH_CODES,
|
NUM_LITERAL_CODES + NUM_LENGTH_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
|
||||||
NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
|
NUM_LITERAL_CODES, NUM_DISTANCE_CODES};
|
||||||
NUM_DISTANCE_CODES
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {
|
static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {0, 1, 1, 1, 0};
|
||||||
0, 1, 1, 1, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NUM_CODE_LENGTH_CODES 19
|
#define NUM_CODE_LENGTH_CODES 19
|
||||||
static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
|
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
|
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
|
#define CODE_TO_PLANE_CODES 120
|
||||||
static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
|
static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
|
||||||
0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
|
0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, 0x26, 0x2a,
|
||||||
0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
|
0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, 0x25, 0x2b, 0x48, 0x04,
|
||||||
0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
|
0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45,
|
||||||
0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
|
0x4b, 0x34, 0x3c, 0x03, 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d,
|
||||||
0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
|
0x44, 0x4c, 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
|
||||||
0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
|
0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, 0x32, 0x3e,
|
||||||
0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
|
0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, 0x64, 0x6c, 0x42, 0x4e,
|
||||||
0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
|
0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e,
|
||||||
0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
|
0x00, 0x74, 0x7c, 0x41, 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d,
|
||||||
0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
|
0x51, 0x5f, 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70};
|
||||||
0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
|
|
||||||
0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
|
|
||||||
};
|
|
||||||
|
|
||||||
// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha
|
// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha
|
||||||
// and distance alphabets are constant (256 for red, blue and alpha, 40 for
|
// and distance alphabets are constant (256 for red, blue and alpha, 40 for
|
||||||
@@ -96,19 +82,10 @@ static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
|
|||||||
// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c
|
// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c
|
||||||
#define FIXED_TABLE_SIZE (630 * 3 + 410)
|
#define FIXED_TABLE_SIZE (630 * 3 + 410)
|
||||||
static const uint16_t kTableSize[12] = {
|
static const uint16_t kTableSize[12] = {
|
||||||
FIXED_TABLE_SIZE + 654,
|
FIXED_TABLE_SIZE + 654, FIXED_TABLE_SIZE + 656, FIXED_TABLE_SIZE + 658,
|
||||||
FIXED_TABLE_SIZE + 656,
|
FIXED_TABLE_SIZE + 662, FIXED_TABLE_SIZE + 670, FIXED_TABLE_SIZE + 686,
|
||||||
FIXED_TABLE_SIZE + 658,
|
FIXED_TABLE_SIZE + 718, FIXED_TABLE_SIZE + 782, FIXED_TABLE_SIZE + 912,
|
||||||
FIXED_TABLE_SIZE + 662,
|
FIXED_TABLE_SIZE + 1168, FIXED_TABLE_SIZE + 1680, FIXED_TABLE_SIZE + 2704};
|
||||||
FIXED_TABLE_SIZE + 670,
|
|
||||||
FIXED_TABLE_SIZE + 686,
|
|
||||||
FIXED_TABLE_SIZE + 718,
|
|
||||||
FIXED_TABLE_SIZE + 782,
|
|
||||||
FIXED_TABLE_SIZE + 912,
|
|
||||||
FIXED_TABLE_SIZE + 1168,
|
|
||||||
FIXED_TABLE_SIZE + 1680,
|
|
||||||
FIXED_TABLE_SIZE + 2704
|
|
||||||
};
|
|
||||||
|
|
||||||
static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
|
static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
|
||||||
// The oldest error reported takes precedence over the new one.
|
// The oldest error reported takes precedence over the new one.
|
||||||
@@ -118,22 +95,19 @@ static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodeImageStream(int xsize, int ysize,
|
static int DecodeImageStream(int xsize, int ysize, int is_level0,
|
||||||
int is_level0,
|
|
||||||
VP8LDecoder* const dec,
|
VP8LDecoder* const dec,
|
||||||
uint32_t** const decoded_data);
|
uint32_t** const decoded_data);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int VP8LCheckSignature(const uint8_t* const data, size_t size) {
|
int VP8LCheckSignature(const uint8_t* const data, size_t size) {
|
||||||
return (size >= VP8L_FRAME_HEADER_SIZE &&
|
return (size >= VP8L_FRAME_HEADER_SIZE && data[0] == VP8L_MAGIC_BYTE &&
|
||||||
data[0] == VP8L_MAGIC_BYTE &&
|
|
||||||
(data[4] >> 5) == 0); // version
|
(data[4] >> 5) == 0); // version
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadImageInfo(VP8LBitReader* const br,
|
static int ReadImageInfo(VP8LBitReader* const br, int* const width,
|
||||||
int* const width, int* const height,
|
int* const height, int* const has_alpha) {
|
||||||
int* const has_alpha) {
|
|
||||||
if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
|
if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
|
||||||
*width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
|
*width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
|
||||||
*height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
|
*height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
|
||||||
@@ -142,8 +116,8 @@ static int ReadImageInfo(VP8LBitReader* const br,
|
|||||||
return !br->eos;
|
return !br->eos;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8LGetInfo(const uint8_t* data, size_t data_size,
|
int VP8LGetInfo(const uint8_t* data, size_t data_size, int* const width,
|
||||||
int* const width, int* const height, int* const has_alpha) {
|
int* const height, int* const has_alpha) {
|
||||||
if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
|
if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
|
||||||
return 0; // not enough data
|
return 0; // not enough data
|
||||||
} else if (!VP8LCheckSignature(data, data_size)) {
|
} else if (!VP8LCheckSignature(data, data_size)) {
|
||||||
@@ -262,8 +236,8 @@ static void BuildPackedTable(HTreeGroup* const htree_group) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadHuffmanCodeLengths(
|
static int ReadHuffmanCodeLengths(VP8LDecoder* const dec,
|
||||||
VP8LDecoder* const dec, const int* const code_length_code_lengths,
|
const int* const code_length_code_lengths,
|
||||||
int num_symbols, int* const code_lengths) {
|
int num_symbols, int* const code_lengths) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
VP8LBitReader* const br = &dec->br;
|
VP8LBitReader* const br = &dec->br;
|
||||||
@@ -316,7 +290,7 @@ static int ReadHuffmanCodeLengths(
|
|||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
VP8LHuffmanTablesDeallocate(&tables);
|
VP8LHuffmanTablesDeallocate(&tables);
|
||||||
if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||||
return ok;
|
return ok;
|
||||||
@@ -348,7 +322,7 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
|||||||
ok = 1;
|
ok = 1;
|
||||||
} else { // Decode Huffman-coded code lengths.
|
} else { // Decode Huffman-coded code lengths.
|
||||||
int i;
|
int i;
|
||||||
int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
|
int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = {0};
|
||||||
const int num_codes = VP8LReadBits(br, 4) + 4;
|
const int num_codes = VP8LReadBits(br, 4) + 4;
|
||||||
assert(num_codes <= NUM_CODE_LENGTH_CODES);
|
assert(num_codes <= NUM_CODE_LENGTH_CODES);
|
||||||
|
|
||||||
@@ -361,8 +335,8 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
|||||||
|
|
||||||
ok = ok && !br->eos;
|
ok = ok && !br->eos;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
|
size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, code_lengths,
|
||||||
code_lengths, alphabet_size);
|
alphabet_size);
|
||||||
}
|
}
|
||||||
if (!ok || size == 0) {
|
if (!ok || size == 0) {
|
||||||
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||||
@@ -449,7 +423,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
|||||||
hdr->num_htree_groups = num_htree_groups;
|
hdr->num_htree_groups = num_htree_groups;
|
||||||
hdr->htree_groups = htree_groups;
|
hdr->htree_groups = htree_groups;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPSafeFree(mapping);
|
WebPSafeFree(mapping);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
WebPSafeFree(huffman_image);
|
WebPSafeFree(huffman_image);
|
||||||
@@ -554,7 +528,7 @@ int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,
|
|||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPSafeFree(code_lengths);
|
WebPSafeFree(code_lengths);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
VP8LHuffmanTablesDeallocate(huffman_tables);
|
VP8LHuffmanTablesDeallocate(huffman_tables);
|
||||||
@@ -595,8 +569,8 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
|
|||||||
scaled_data = (uint32_t*)memory;
|
scaled_data = (uint32_t*)memory;
|
||||||
|
|
||||||
if (!WebPRescalerInit(dec->rescaler, in_width, in_height,
|
if (!WebPRescalerInit(dec->rescaler, in_width, in_height,
|
||||||
(uint8_t*)scaled_data, out_width, out_height,
|
(uint8_t*)scaled_data, out_width, out_height, 0,
|
||||||
0, num_channels, work)) {
|
num_channels, work)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -626,9 +600,9 @@ static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit scaled rows.
|
// Emit scaled rows.
|
||||||
static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
|
static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, uint8_t* in,
|
||||||
uint8_t* in, int in_stride, int mb_h,
|
int in_stride, int mb_h, uint8_t* const out,
|
||||||
uint8_t* const out, int out_stride) {
|
int out_stride) {
|
||||||
const WEBP_CSP_MODE colorspace = dec->output->colorspace;
|
const WEBP_CSP_MODE colorspace = dec->output->colorspace;
|
||||||
int num_lines_in = 0;
|
int num_lines_in = 0;
|
||||||
int num_lines_out = 0;
|
int num_lines_out = 0;
|
||||||
@@ -639,8 +613,8 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
|
|||||||
const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
|
const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
|
||||||
int lines_imported;
|
int lines_imported;
|
||||||
assert(needed_lines > 0 && needed_lines <= lines_left);
|
assert(needed_lines > 0 && needed_lines <= lines_left);
|
||||||
WebPMultARGBRows(row_in, in_stride,
|
WebPMultARGBRows(row_in, in_stride, dec->rescaler->src_width, needed_lines,
|
||||||
dec->rescaler->src_width, needed_lines, 0);
|
0);
|
||||||
lines_imported =
|
lines_imported =
|
||||||
WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
|
WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
|
||||||
assert(lines_imported == needed_lines);
|
assert(lines_imported == needed_lines);
|
||||||
@@ -653,10 +627,9 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
|
|||||||
#endif // WEBP_REDUCE_SIZE
|
#endif // WEBP_REDUCE_SIZE
|
||||||
|
|
||||||
// Emit rows without any scaling.
|
// Emit rows without any scaling.
|
||||||
static int EmitRows(WEBP_CSP_MODE colorspace,
|
static int EmitRows(WEBP_CSP_MODE colorspace, const uint8_t* row_in,
|
||||||
const uint8_t* row_in, int in_stride,
|
int in_stride, int mb_w, int mb_h, uint8_t* const out,
|
||||||
int mb_w, int mb_h,
|
int out_stride) {
|
||||||
uint8_t* const out, int out_stride) {
|
|
||||||
int lines = mb_h;
|
int lines = mb_h;
|
||||||
uint8_t* row_out = out;
|
uint8_t* row_out = out;
|
||||||
while (lines-- > 0) {
|
while (lines-- > 0) {
|
||||||
@@ -711,8 +684,8 @@ static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
|
|||||||
return num_lines_out;
|
return num_lines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
|
static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, uint8_t* in,
|
||||||
uint8_t* in, int in_stride, int mb_h) {
|
int in_stride, int mb_h) {
|
||||||
int num_lines_in = 0;
|
int num_lines_in = 0;
|
||||||
int y_pos = dec->last_out_row;
|
int y_pos = dec->last_out_row;
|
||||||
while (num_lines_in < mb_h) {
|
while (num_lines_in < mb_h) {
|
||||||
@@ -730,9 +703,8 @@ static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
|
|||||||
return y_pos;
|
return y_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int EmitRowsYUVA(const VP8LDecoder* const dec,
|
static int EmitRowsYUVA(const VP8LDecoder* const dec, const uint8_t* in,
|
||||||
const uint8_t* in, int in_stride,
|
int in_stride, int mb_w, int num_rows) {
|
||||||
int mb_w, int num_rows) {
|
|
||||||
int y_pos = dec->last_out_row;
|
int y_pos = dec->last_out_row;
|
||||||
while (num_rows-- > 0) {
|
while (num_rows-- > 0) {
|
||||||
ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output);
|
ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output);
|
||||||
@@ -774,8 +746,8 @@ static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static WEBP_INLINE int GetMetaIndex(
|
static WEBP_INLINE int GetMetaIndex(const uint32_t* const image, int xsize,
|
||||||
const uint32_t* const image, int xsize, int bits, int x, int y) {
|
int bits, int x, int y) {
|
||||||
if (bits == 0) return 0;
|
if (bits == 0) return 0;
|
||||||
return image[xsize * (y >> bits) + (x >> bits)];
|
return image[xsize * (y >> bits) + (x >> bits)];
|
||||||
}
|
}
|
||||||
@@ -793,9 +765,8 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
|
|||||||
|
|
||||||
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
|
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
|
||||||
|
|
||||||
static void ApplyInverseTransforms(VP8LDecoder* const dec,
|
static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_row,
|
||||||
int start_row, int num_rows,
|
int num_rows, const uint32_t* const rows) {
|
||||||
const uint32_t* const rows) {
|
|
||||||
int n = dec->next_transform;
|
int n = dec->next_transform;
|
||||||
const int cache_pixs = dec->width * num_rows;
|
const int cache_pixs = dec->width * num_rows;
|
||||||
const int end_row = start_row + num_rows;
|
const int end_row = start_row + num_rows;
|
||||||
@@ -839,18 +810,19 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
|
|||||||
buf->rgba + (ptrdiff_t)dec->last_out_row * buf->stride;
|
buf->rgba + (ptrdiff_t)dec->last_out_row * buf->stride;
|
||||||
const int num_rows_out =
|
const int num_rows_out =
|
||||||
#if !defined(WEBP_REDUCE_SIZE)
|
#if !defined(WEBP_REDUCE_SIZE)
|
||||||
io->use_scaling ?
|
io->use_scaling ? EmitRescaledRowsRGBA(dec, rows_data, in_stride,
|
||||||
EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
|
io->mb_h, rgba, buf->stride)
|
||||||
rgba, buf->stride) :
|
:
|
||||||
#endif // WEBP_REDUCE_SIZE
|
#endif // WEBP_REDUCE_SIZE
|
||||||
EmitRows(output->colorspace, rows_data, in_stride,
|
EmitRows(output->colorspace, rows_data, in_stride,
|
||||||
io->mb_w, io->mb_h, rgba, buf->stride);
|
io->mb_w, io->mb_h, rgba, buf->stride);
|
||||||
// Update 'last_out_row'.
|
// Update 'last_out_row'.
|
||||||
dec->last_out_row += num_rows_out;
|
dec->last_out_row += num_rows_out;
|
||||||
} else { // convert to YUVA
|
} else { // convert to YUVA
|
||||||
dec->last_out_row = io->use_scaling ?
|
dec->last_out_row =
|
||||||
EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
|
io->use_scaling
|
||||||
EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
|
? 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);
|
assert(dec->last_out_row <= output->height);
|
||||||
}
|
}
|
||||||
@@ -877,9 +849,8 @@ static int Is8bOptimizable(const VP8LMetadata* const hdr) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AlphaApplyFilter(ALPHDecoder* const alph_dec,
|
static void AlphaApplyFilter(ALPHDecoder* const alph_dec, int first_row,
|
||||||
int first_row, int last_row,
|
int last_row, uint8_t* out, int stride) {
|
||||||
uint8_t* out, int stride) {
|
|
||||||
if (alph_dec->filter != WEBP_FILTER_NONE) {
|
if (alph_dec->filter != WEBP_FILTER_NONE) {
|
||||||
int y;
|
int y;
|
||||||
const uint8_t* prev_line = alph_dec->prev_line;
|
const uint8_t* prev_line = alph_dec->prev_line;
|
||||||
@@ -897,9 +868,9 @@ static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
|
|||||||
// For vertical and gradient filtering, we need to decode the part above the
|
// For vertical and gradient filtering, we need to decode the part above the
|
||||||
// crop_top row, in order to have the correct spatial predictors.
|
// crop_top row, in order to have the correct spatial predictors.
|
||||||
ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io->opaque;
|
ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io->opaque;
|
||||||
const int top_row =
|
const int top_row = (alph_dec->filter == WEBP_FILTER_NONE ||
|
||||||
(alph_dec->filter == WEBP_FILTER_NONE ||
|
alph_dec->filter == WEBP_FILTER_HORIZONTAL)
|
||||||
alph_dec->filter == WEBP_FILTER_HORIZONTAL) ? dec->io->crop_top
|
? dec->io->crop_top
|
||||||
: dec->last_row;
|
: dec->last_row;
|
||||||
const int first_row = (dec->last_row < top_row) ? top_row : dec->last_row;
|
const int first_row = (dec->last_row < top_row) ? top_row : dec->last_row;
|
||||||
assert(last_row <= dec->io->crop_bottom);
|
assert(last_row <= dec->io->crop_bottom);
|
||||||
@@ -907,13 +878,12 @@ static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
|
|||||||
// Special method for paletted alpha data. We only process the cropped area.
|
// Special method for paletted alpha data. We only process the cropped area.
|
||||||
const int width = dec->io->width;
|
const int width = dec->io->width;
|
||||||
uint8_t* out = alph_dec->output + width * first_row;
|
uint8_t* out = alph_dec->output + width * first_row;
|
||||||
const uint8_t* const in =
|
const uint8_t* const in = (uint8_t*)dec->pixels + dec->width * first_row;
|
||||||
(uint8_t*)dec->pixels + dec->width * first_row;
|
|
||||||
VP8LTransform* const transform = &dec->transforms[0];
|
VP8LTransform* const transform = &dec->transforms[0];
|
||||||
assert(dec->next_transform == 1);
|
assert(dec->next_transform == 1);
|
||||||
assert(transform->type == COLOR_INDEXING_TRANSFORM);
|
assert(transform->type == COLOR_INDEXING_TRANSFORM);
|
||||||
VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,
|
VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row, in,
|
||||||
in, out);
|
out);
|
||||||
AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
|
AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
|
||||||
}
|
}
|
||||||
dec->last_row = dec->last_out_row = last_row;
|
dec->last_row = dec->last_out_row = last_row;
|
||||||
@@ -963,7 +933,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
|
|||||||
pattern |= pattern << 8;
|
pattern |= pattern << 8;
|
||||||
pattern |= pattern << 16;
|
pattern |= pattern << 16;
|
||||||
#elif defined(WEBP_USE_MIPS_DSP_R2)
|
#elif defined(WEBP_USE_MIPS_DSP_R2)
|
||||||
__asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));
|
__asm__ volatile("replv.qb %0, %0" : "+r"(pattern));
|
||||||
#else
|
#else
|
||||||
pattern = 0x01010101u * pattern;
|
pattern = 0x01010101u * pattern;
|
||||||
#endif
|
#endif
|
||||||
@@ -977,7 +947,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
|
|||||||
#if defined(__arm__) || defined(_M_ARM)
|
#if defined(__arm__) || defined(_M_ARM)
|
||||||
pattern |= pattern << 16;
|
pattern |= pattern << 16;
|
||||||
#elif defined(WEBP_USE_MIPS_DSP_R2)
|
#elif defined(WEBP_USE_MIPS_DSP_R2)
|
||||||
__asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));
|
__asm__ volatile("replv.ph %0, %0" : "+r"(pattern));
|
||||||
#else
|
#else
|
||||||
pattern = 0x00010001u * pattern;
|
pattern = 0x00010001u * pattern;
|
||||||
#endif
|
#endif
|
||||||
@@ -991,7 +961,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
|
|||||||
CopySmallPattern8b(src, dst, length, pattern);
|
CopySmallPattern8b(src, dst, length, pattern);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Copy:
|
Copy:
|
||||||
if (dist >= length) { // no overlap -> use memcpy()
|
if (dist >= length) { // no overlap -> use memcpy()
|
||||||
memcpy(dst, src, length * sizeof(*dst));
|
memcpy(dst, src, length * sizeof(*dst));
|
||||||
} else {
|
} else {
|
||||||
@@ -1001,8 +971,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copy pattern of 1 or 2 uint32_t's
|
// copy pattern of 1 or 2 uint32_t's
|
||||||
static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,
|
static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src, uint32_t* dst,
|
||||||
uint32_t* dst,
|
|
||||||
int length, uint64_t pattern) {
|
int length, uint64_t pattern) {
|
||||||
int i;
|
int i;
|
||||||
if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.
|
if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.
|
||||||
@@ -1019,8 +988,8 @@ static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,
|
static WEBP_INLINE void CopyBlock32b(uint32_t* const dst, int dist,
|
||||||
int dist, int length) {
|
int length) {
|
||||||
const uint32_t* const src = dst - dist;
|
const uint32_t* const src = dst - dist;
|
||||||
if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {
|
if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {
|
||||||
uint64_t pattern;
|
uint64_t pattern;
|
||||||
@@ -1114,7 +1083,7 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
|
|||||||
// Process the remaining rows corresponding to last row-block.
|
// Process the remaining rows corresponding to last row-block.
|
||||||
ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);
|
ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);
|
||||||
|
|
||||||
End:
|
End:
|
||||||
br->eos = VP8LIsEndOfStream(br);
|
br->eos = VP8LIsEndOfStream(br);
|
||||||
if (!ok || (br->eos && pos < end)) {
|
if (!ok || (br->eos && pos < end)) {
|
||||||
return VP8LSetError(
|
return VP8LSetError(
|
||||||
@@ -1297,7 +1266,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1314,9 +1283,8 @@ static void ClearTransform(VP8LTransform* const transform) {
|
|||||||
static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
|
static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
|
||||||
int i;
|
int i;
|
||||||
const int final_num_colors = 1 << (8 >> transform->bits);
|
const int final_num_colors = 1 << (8 >> transform->bits);
|
||||||
uint32_t* const new_color_map =
|
uint32_t* const new_color_map = (uint32_t*)WebPSafeMalloc(
|
||||||
(uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
|
(uint64_t)final_num_colors, sizeof(*new_color_map));
|
||||||
sizeof(*new_color_map));
|
|
||||||
if (new_color_map == NULL) {
|
if (new_color_map == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -1362,10 +1330,9 @@ static int ReadTransform(int* const xsize, int const* ysize,
|
|||||||
case CROSS_COLOR_TRANSFORM:
|
case CROSS_COLOR_TRANSFORM:
|
||||||
transform->bits =
|
transform->bits =
|
||||||
MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);
|
MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);
|
||||||
ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize,
|
ok = DecodeImageStream(
|
||||||
transform->bits),
|
VP8LSubSampleSize(transform->xsize, transform->bits),
|
||||||
VP8LSubSampleSize(transform->ysize,
|
VP8LSubSampleSize(transform->ysize, transform->bits),
|
||||||
transform->bits),
|
|
||||||
/*is_level0=*/0, dec, &transform->data);
|
/*is_level0=*/0, dec, &transform->data);
|
||||||
break;
|
break;
|
||||||
case COLOR_INDEXING_TRANSFORM: {
|
case COLOR_INDEXING_TRANSFORM: {
|
||||||
@@ -1464,8 +1431,7 @@ static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
|
|||||||
hdr->huffman_mask = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
|
hdr->huffman_mask = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodeImageStream(int xsize, int ysize,
|
static int DecodeImageStream(int xsize, int ysize, int is_level0,
|
||||||
int is_level0,
|
|
||||||
VP8LDecoder* const dec,
|
VP8LDecoder* const dec,
|
||||||
uint32_t** const decoded_data) {
|
uint32_t** const decoded_data) {
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
@@ -1532,7 +1498,7 @@ static int DecodeImageStream(int xsize, int ysize,
|
|||||||
transform_ysize, NULL);
|
transform_ysize, NULL);
|
||||||
ok = ok && !br->eos;
|
ok = ok && !br->eos;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
WebPSafeFree(data);
|
WebPSafeFree(data);
|
||||||
ClearMetadata(hdr);
|
ClearMetadata(hdr);
|
||||||
@@ -1604,8 +1570,8 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
|
|||||||
const uint32_t* const src = dec->argb_cache;
|
const uint32_t* const src = dec->argb_cache;
|
||||||
ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
|
ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
|
||||||
WebPExtractGreen(src, dst, cache_pixs);
|
WebPExtractGreen(src, dst, cache_pixs);
|
||||||
AlphaApplyFilter(alph_dec,
|
AlphaApplyFilter(alph_dec, cur_row, cur_row + num_rows_to_process, dst,
|
||||||
cur_row, cur_row + num_rows_to_process, dst, width);
|
width);
|
||||||
num_rows -= num_rows_to_process;
|
num_rows -= num_rows_to_process;
|
||||||
in += num_rows_to_process * dec->width;
|
in += num_rows_to_process * dec->width;
|
||||||
cur_row += num_rows_to_process;
|
cur_row += num_rows_to_process;
|
||||||
@@ -1658,7 +1624,7 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
|
|||||||
alph_dec->vp8l_dec = dec;
|
alph_dec->vp8l_dec = dec;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Err:
|
Err:
|
||||||
VP8LDelete(dec);
|
VP8LDelete(dec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1675,10 +1641,10 @@ int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
|
|||||||
if (!alph_dec->use_8b_decode) WebPInitAlphaProcessing();
|
if (!alph_dec->use_8b_decode) WebPInitAlphaProcessing();
|
||||||
|
|
||||||
// Decode (with special row processing).
|
// Decode (with special row processing).
|
||||||
return alph_dec->use_8b_decode ?
|
return alph_dec->use_8b_decode
|
||||||
DecodeAlphaData(dec, (uint8_t*)dec->pixels, dec->width, dec->height,
|
? DecodeAlphaData(dec, (uint8_t*)dec->pixels, dec->width,
|
||||||
last_row) :
|
dec->height, last_row)
|
||||||
DecodeImageData(dec, dec->pixels, dec->width, dec->height,
|
: DecodeImageData(dec, dec->pixels, dec->width, dec->height,
|
||||||
last_row, ExtractAlphaRows);
|
last_row, ExtractAlphaRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1709,7 +1675,7 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
VP8LClear(dec);
|
VP8LClear(dec);
|
||||||
assert(dec->status != VP8_STATUS_OK);
|
assert(dec->status != VP8_STATUS_OK);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1781,7 +1747,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
|||||||
params->last_y = dec->last_out_row;
|
params->last_y = dec->last_out_row;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Err:
|
Err:
|
||||||
VP8LClear(dec);
|
VP8LClear(dec);
|
||||||
assert(dec->status != VP8_STATUS_OK);
|
assert(dec->status != VP8_STATUS_OK);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -31,11 +31,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum { READ_DATA = 0, READ_HDR = 1, READ_DIM = 2 } VP8LDecodeState;
|
||||||
READ_DATA = 0,
|
|
||||||
READ_HDR = 1,
|
|
||||||
READ_DIM = 2
|
|
||||||
} VP8LDecodeState;
|
|
||||||
|
|
||||||
typedef struct VP8LTransform VP8LTransform;
|
typedef struct VP8LTransform VP8LTransform;
|
||||||
struct VP8LTransform {
|
struct VP8LTransform {
|
||||||
|
|||||||
@@ -99,8 +99,7 @@ static VP8StatusCode ParseRIFF(const uint8_t** const data,
|
|||||||
// *height_ptr and *flags_ptr are set to the corresponding values extracted
|
// *height_ptr and *flags_ptr are set to the corresponding values extracted
|
||||||
// from the VP8X chunk.
|
// from the VP8X chunk.
|
||||||
static VP8StatusCode ParseVP8X(const uint8_t** const data,
|
static VP8StatusCode ParseVP8X(const uint8_t** const data,
|
||||||
size_t* const data_size,
|
size_t* const data_size, int* const found_vp8x,
|
||||||
int* const found_vp8x,
|
|
||||||
int* const width_ptr, int* const height_ptr,
|
int* const width_ptr, int* const height_ptr,
|
||||||
uint32_t* const flags_ptr) {
|
uint32_t* const flags_ptr) {
|
||||||
const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
|
const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
|
||||||
@@ -199,8 +198,7 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
|
|||||||
// parsed all the optional chunks.
|
// parsed all the optional chunks.
|
||||||
// Note: This check must occur before the check 'buf_size < disk_chunk_size'
|
// Note: This check must occur before the check 'buf_size < disk_chunk_size'
|
||||||
// below to allow incomplete VP8/VP8L chunks.
|
// below to allow incomplete VP8/VP8L chunks.
|
||||||
if (!memcmp(buf, "VP8 ", TAG_SIZE) ||
|
if (!memcmp(buf, "VP8 ", TAG_SIZE) || !memcmp(buf, "VP8L", TAG_SIZE)) {
|
||||||
!memcmp(buf, "VP8L", TAG_SIZE)) {
|
|
||||||
return VP8_STATUS_OK;
|
return VP8_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,10 +280,8 @@ static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr,
|
|||||||
// RIFF + VP8X + (optional chunks) + VP8(L)
|
// RIFF + VP8X + (optional chunks) + VP8(L)
|
||||||
// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
|
// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
|
||||||
// VP8(L) <-- 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,
|
static VP8StatusCode ParseHeadersInternal(const uint8_t* data, size_t data_size,
|
||||||
size_t data_size,
|
int* const width, int* const height,
|
||||||
int* const width,
|
|
||||||
int* const height,
|
|
||||||
int* const has_alpha,
|
int* const has_alpha,
|
||||||
int* const has_animation,
|
int* const has_animation,
|
||||||
int* const format,
|
int* const format,
|
||||||
@@ -319,8 +315,8 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
|||||||
// Skip over VP8X.
|
// Skip over VP8X.
|
||||||
{
|
{
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
status = ParseVP8X(&data, &data_size, &found_vp8x,
|
status = ParseVP8X(&data, &data_size, &found_vp8x, &canvas_width,
|
||||||
&canvas_width, &canvas_height, &flags);
|
&canvas_height, &flags);
|
||||||
if (status != VP8_STATUS_OK) {
|
if (status != VP8_STATUS_OK) {
|
||||||
return status; // Wrong VP8X / insufficient data.
|
return status; // Wrong VP8X / insufficient data.
|
||||||
}
|
}
|
||||||
@@ -403,7 +399,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
|||||||
assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
|
assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
|
||||||
assert(headers->offset == headers->data_size - data_size);
|
assert(headers->offset == headers->data_size - data_size);
|
||||||
}
|
}
|
||||||
ReturnWidthHeight:
|
ReturnWidthHeight:
|
||||||
if (status == VP8_STATUS_OK ||
|
if (status == VP8_STATUS_OK ||
|
||||||
(status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) {
|
(status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) {
|
||||||
if (has_alpha != NULL) {
|
if (has_alpha != NULL) {
|
||||||
@@ -425,9 +421,8 @@ VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
|
|||||||
int has_animation = 0;
|
int has_animation = 0;
|
||||||
assert(headers != NULL);
|
assert(headers != NULL);
|
||||||
// fill out headers, ignore width/height/has_alpha.
|
// fill out headers, ignore width/height/has_alpha.
|
||||||
status = ParseHeadersInternal(headers->data, headers->data_size,
|
status = ParseHeadersInternal(headers->data, headers->data_size, NULL, NULL,
|
||||||
NULL, NULL, NULL, &has_animation,
|
NULL, &has_animation, NULL, headers);
|
||||||
NULL, headers);
|
|
||||||
if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) {
|
if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) {
|
||||||
// The WebPDemux API + libwebp can be used to decode individual
|
// The WebPDemux API + libwebp can be used to decode individual
|
||||||
// uncomposited frames or the WebPAnimDecoder can be used to fully
|
// uncomposited frames or the WebPAnimDecoder can be used to fully
|
||||||
@@ -492,8 +487,8 @@ WEBP_NODISCARD static VP8StatusCode DecodeInto(const uint8_t* const data,
|
|||||||
params->output);
|
params->output);
|
||||||
if (status == VP8_STATUS_OK) { // Decode
|
if (status == VP8_STATUS_OK) { // Decode
|
||||||
// This change must be done before calling VP8Decode()
|
// This change must be done before calling VP8Decode()
|
||||||
dec->mt_method = VP8GetThreadMethod(params->options, &headers,
|
dec->mt_method =
|
||||||
io.width, io.height);
|
VP8GetThreadMethod(params->options, &headers, io.width, io.height);
|
||||||
VP8InitDithering(params->options, dec);
|
VP8InitDithering(params->options, dec);
|
||||||
if (!VP8Decode(dec, &io)) {
|
if (!VP8Decode(dec, &io)) {
|
||||||
status = dec->status;
|
status = dec->status;
|
||||||
@@ -582,10 +577,10 @@ uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size,
|
|||||||
return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size);
|
return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, uint8_t* luma,
|
||||||
uint8_t* luma, size_t luma_size, int luma_stride,
|
size_t luma_size, int luma_stride, uint8_t* u,
|
||||||
uint8_t* u, size_t u_size, int u_stride,
|
size_t u_size, int u_stride, uint8_t* v,
|
||||||
uint8_t* v, size_t v_size, int v_stride) {
|
size_t v_size, int v_stride) {
|
||||||
WebPDecParams params;
|
WebPDecParams params;
|
||||||
WebPDecBuffer output;
|
WebPDecBuffer output;
|
||||||
if (luma == NULL || !WebPInitDecBuffer(&output)) return NULL;
|
if (luma == NULL || !WebPInitDecBuffer(&output)) return NULL;
|
||||||
@@ -643,34 +638,34 @@ WEBP_NODISCARD static uint8_t* Decode(WEBP_CSP_MODE mode,
|
|||||||
return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
|
return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height) {
|
int* height) {
|
||||||
return Decode(MODE_RGB, data, data_size, width, height, NULL);
|
return Decode(MODE_RGB, data, data_size, width, height, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height) {
|
int* height) {
|
||||||
return Decode(MODE_RGBA, data, data_size, width, height, NULL);
|
return Decode(MODE_RGBA, data, data_size, width, height, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height) {
|
int* height) {
|
||||||
return Decode(MODE_ARGB, data, data_size, width, height, NULL);
|
return Decode(MODE_ARGB, data, data_size, width, height, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height) {
|
int* height) {
|
||||||
return Decode(MODE_BGR, data, data_size, width, height, NULL);
|
return Decode(MODE_BGR, data, data_size, width, height, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height) {
|
int* height) {
|
||||||
return Decode(MODE_BGRA, data, data_size, width, height, NULL);
|
return Decode(MODE_BGRA, data, data_size, width, height, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
|
uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height, uint8_t** u, uint8_t** v,
|
int* height, uint8_t** u, uint8_t** v, int* stride,
|
||||||
int* stride, int* uv_stride) {
|
int* uv_stride) {
|
||||||
// data, width and height are checked by Decode().
|
// data, width and height are checked by Decode().
|
||||||
if (u == NULL || v == NULL || stride == NULL || uv_stride == NULL) {
|
if (u == NULL || v == NULL || stride == NULL || uv_stride == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -678,8 +673,8 @@ uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
|
|||||||
|
|
||||||
{
|
{
|
||||||
WebPDecBuffer output; // only to preserve the side-infos
|
WebPDecBuffer output; // only to preserve the side-infos
|
||||||
uint8_t* const out = Decode(MODE_YUV, data, data_size,
|
uint8_t* const out =
|
||||||
width, height, &output);
|
Decode(MODE_YUV, data, data_size, width, height, &output);
|
||||||
|
|
||||||
if (out != NULL) {
|
if (out != NULL) {
|
||||||
const WebPYUVABuffer* const buf = &output.u.YUVA;
|
const WebPYUVABuffer* const buf = &output.u.YUVA;
|
||||||
@@ -706,17 +701,16 @@ static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
|
|||||||
DefaultFeatures(features);
|
DefaultFeatures(features);
|
||||||
|
|
||||||
// Only parse enough of the data to retrieve the features.
|
// Only parse enough of the data to retrieve the features.
|
||||||
return ParseHeadersInternal(data, data_size,
|
return ParseHeadersInternal(
|
||||||
&features->width, &features->height,
|
data, data_size, &features->width, &features->height,
|
||||||
&features->has_alpha, &features->has_animation,
|
&features->has_alpha, &features->has_animation, &features->format, NULL);
|
||||||
&features->format, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// WebPGetInfo()
|
// WebPGetInfo()
|
||||||
|
|
||||||
int WebPGetInfo(const uint8_t* data, size_t data_size,
|
int WebPGetInfo(const uint8_t* data, size_t data_size, int* width,
|
||||||
int* width, int* height) {
|
int* height) {
|
||||||
WebPBitstreamFeatures features;
|
WebPBitstreamFeatures features;
|
||||||
|
|
||||||
if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) {
|
if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) {
|
||||||
@@ -736,8 +730,7 @@ int WebPGetInfo(const uint8_t* data, size_t data_size,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Advance decoding API
|
// Advance decoding API
|
||||||
|
|
||||||
int WebPInitDecoderConfigInternal(WebPDecoderConfig* config,
|
int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, int version) {
|
||||||
int version) {
|
|
||||||
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
|
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
|
||||||
return 0; // version mismatch
|
return 0; // version mismatch
|
||||||
}
|
}
|
||||||
@@ -864,8 +857,8 @@ VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Cropping and rescaling.
|
// Cropping and rescaling.
|
||||||
|
|
||||||
int WebPCheckCropDimensions(int image_width, int image_height,
|
int WebPCheckCropDimensions(int image_width, int image_height, int x, int y,
|
||||||
int x, int y, int w, int h) {
|
int w, int h) {
|
||||||
return WebPCheckCropDimensionsBasic(x, y, w, h) &&
|
return WebPCheckCropDimensionsBasic(x, y, w, h) &&
|
||||||
!(x >= image_width || w > image_width || w > image_width - x ||
|
!(x >= image_width || w > image_width || w > image_width - x ||
|
||||||
y >= image_height || h > image_height || h > image_height - y);
|
y >= image_height || h > image_height || h > image_height - y);
|
||||||
@@ -921,8 +914,8 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
|
|||||||
|
|
||||||
if (io->use_scaling) {
|
if (io->use_scaling) {
|
||||||
// disable filter (only for large downscaling ratio).
|
// disable filter (only for large downscaling ratio).
|
||||||
io->bypass_filtering |= (io->scaled_width < W * 3 / 4) &&
|
io->bypass_filtering |=
|
||||||
(io->scaled_height < H * 3 / 4);
|
(io->scaled_width < W * 3 / 4) && (io->scaled_height < H * 3 / 4);
|
||||||
io->fancy_upsampling = 0;
|
io->fancy_upsampling = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos,
|
|||||||
|
|
||||||
struct WebPDecParams {
|
struct WebPDecParams {
|
||||||
WebPDecBuffer* output; // output buffer.
|
WebPDecBuffer* output; // output buffer.
|
||||||
uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler
|
uint8_t *tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler
|
||||||
// or used for tmp rescaling
|
// or used for tmp rescaling
|
||||||
|
|
||||||
int last_y; // coordinate of the line that was last output
|
int last_y; // coordinate of the line that was last output
|
||||||
const WebPDecoderOptions* options; // if not NULL, use alt decoding features
|
const WebPDecoderOptions* options; // if not NULL, use alt decoding features
|
||||||
|
|
||||||
WebPRescaler* scaler_y, *scaler_u, *scaler_v, *scaler_a; // rescalers
|
WebPRescaler *scaler_y, *scaler_u, *scaler_v, *scaler_a; // rescalers
|
||||||
void* memory; // overall scratch memory for the output work.
|
void* memory; // overall scratch memory for the output work.
|
||||||
|
|
||||||
OutputFunc emit; // output RGB or YUV samples
|
OutputFunc emit; // output RGB or YUV samples
|
||||||
@@ -82,8 +82,8 @@ VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
|
|||||||
// Misc utils
|
// Misc utils
|
||||||
|
|
||||||
// Returns true if crop dimensions are within image bounds.
|
// Returns true if crop dimensions are within image bounds.
|
||||||
int WebPCheckCropDimensions(int image_width, int image_height,
|
int WebPCheckCropDimensions(int image_width, int image_height, int x, int y,
|
||||||
int x, int y, int w, int h);
|
int w, int h);
|
||||||
|
|
||||||
// Initializes VP8Io with custom setup, io and teardown functions. The default
|
// Initializes VP8Io with custom setup, io and teardown functions. The default
|
||||||
// hooks will use the supplied 'params' as io->opaque handle.
|
// hooks will use the supplied 'params' as io->opaque handle.
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ WEBP_NODISCARD static int ApplyDecoderOptions(
|
|||||||
assert(dec_options != NULL);
|
assert(dec_options != NULL);
|
||||||
|
|
||||||
mode = dec_options->color_mode;
|
mode = dec_options->color_mode;
|
||||||
if (mode != MODE_RGBA && mode != MODE_BGRA &&
|
if (mode != MODE_RGBA && mode != MODE_BGRA && mode != MODE_rgbA &&
|
||||||
mode != MODE_rgbA && mode != MODE_bgrA) {
|
mode != MODE_bgrA) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dec->blend_func = (mode == MODE_RGBA || mode == MODE_BGRA)
|
dec->blend_func = (mode == MODE_RGBA || mode == MODE_BGRA)
|
||||||
@@ -145,7 +145,7 @@ WebPAnimDecoder* WebPAnimDecoderNewInternal(
|
|||||||
WebPAnimDecoderReset(dec);
|
WebPAnimDecoderReset(dec);
|
||||||
return dec;
|
return dec;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPAnimDecoderDelete(dec);
|
WebPAnimDecoderDelete(dec);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -197,13 +197,13 @@ WEBP_NODISCARD static int CopyCanvas(const uint8_t* src, uint8_t* dst,
|
|||||||
// Returns true if the current frame is a key-frame.
|
// Returns true if the current frame is a key-frame.
|
||||||
static int IsKeyFrame(const WebPIterator* const curr,
|
static int IsKeyFrame(const WebPIterator* const curr,
|
||||||
const WebPIterator* const prev,
|
const WebPIterator* const prev,
|
||||||
int prev_frame_was_key_frame,
|
int prev_frame_was_key_frame, int canvas_width,
|
||||||
int canvas_width, int canvas_height) {
|
int canvas_height) {
|
||||||
if (curr->frame_num == 1) {
|
if (curr->frame_num == 1) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) &&
|
} else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) &&
|
||||||
IsFullFrame(curr->width, curr->height,
|
IsFullFrame(curr->width, curr->height, canvas_width,
|
||||||
canvas_width, canvas_height)) {
|
canvas_height)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) &&
|
return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) &&
|
||||||
@@ -213,12 +213,11 @@ static int IsKeyFrame(const WebPIterator* const curr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Blend a single channel of 'src' over 'dst', given their alpha channel values.
|
// Blend a single channel of 'src' over 'dst', given their alpha channel values.
|
||||||
// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha.
|
// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha.
|
||||||
static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a,
|
static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, uint32_t dst,
|
||||||
uint32_t dst, uint8_t dst_a,
|
uint8_t dst_a, uint32_t scale,
|
||||||
uint32_t scale, int shift) {
|
int shift) {
|
||||||
const uint8_t src_channel = (src >> shift) & 0xff;
|
const uint8_t src_channel = (src >> shift) & 0xff;
|
||||||
const uint8_t dst_channel = (dst >> shift) & 0xff;
|
const uint8_t dst_channel = (dst >> shift) & 0xff;
|
||||||
const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a;
|
const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a;
|
||||||
@@ -328,8 +327,8 @@ static void FindBlendRangeAtRow(const WebPIterator* const src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
|
int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, uint8_t** buf_ptr,
|
||||||
uint8_t** buf_ptr, int* timestamp_ptr) {
|
int* timestamp_ptr) {
|
||||||
WebPIterator iter;
|
WebPIterator iter;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
@@ -358,8 +357,7 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
|
|||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!CopyCanvas(dec->prev_frame_disposed, dec->curr_frame,
|
if (!CopyCanvas(dec->prev_frame_disposed, dec->curr_frame, width, height)) {
|
||||||
width, height)) {
|
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,8 +392,7 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
|
|||||||
int y;
|
int y;
|
||||||
// Blend transparent pixels with pixels in previous canvas.
|
// Blend transparent pixels with pixels in previous canvas.
|
||||||
for (y = 0; y < iter.height; ++y) {
|
for (y = 0; y < iter.height; ++y) {
|
||||||
const size_t offset =
|
const size_t offset = (iter.y_offset + y) * width + iter.x_offset;
|
||||||
(iter.y_offset + y) * width + iter.x_offset;
|
|
||||||
blend_row((uint32_t*)dec->curr_frame + offset,
|
blend_row((uint32_t*)dec->curr_frame + offset,
|
||||||
(uint32_t*)dec->prev_frame_disposed + offset, iter.width);
|
(uint32_t*)dec->prev_frame_disposed + offset, iter.width);
|
||||||
}
|
}
|
||||||
@@ -445,7 +442,7 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
|
|||||||
*timestamp_ptr = timestamp;
|
*timestamp_ptr = timestamp;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPDemuxReleaseIterator(&iter);
|
WebPDemuxReleaseIterator(&iter);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,11 +76,7 @@ struct WebPDemuxer {
|
|||||||
Chunk** chunks_tail;
|
Chunk** chunks_tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum { PARSE_OK, PARSE_NEED_MORE_DATA, PARSE_ERROR } ParseStatus;
|
||||||
PARSE_OK,
|
|
||||||
PARSE_NEED_MORE_DATA,
|
|
||||||
PARSE_ERROR
|
|
||||||
} ParseStatus;
|
|
||||||
|
|
||||||
typedef struct ChunkParser {
|
typedef struct ChunkParser {
|
||||||
uint8_t id[4];
|
uint8_t id[4];
|
||||||
@@ -94,10 +90,10 @@ static int IsValidSimpleFormat(const WebPDemuxer* const dmux);
|
|||||||
static int IsValidExtendedFormat(const WebPDemuxer* const dmux);
|
static int IsValidExtendedFormat(const WebPDemuxer* const dmux);
|
||||||
|
|
||||||
static const ChunkParser kMasterChunks[] = {
|
static const ChunkParser kMasterChunks[] = {
|
||||||
{ { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat },
|
{{'V', 'P', '8', ' '}, ParseSingleImage, IsValidSimpleFormat},
|
||||||
{ { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat },
|
{{'V', 'P', '8', 'L'}, ParseSingleImage, IsValidSimpleFormat},
|
||||||
{ { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat },
|
{{'V', 'P', '8', 'X'}, ParseVP8X, IsValidExtendedFormat},
|
||||||
{ { '0', '0', '0', '0' }, NULL, NULL },
|
{{'0', '0', '0', '0'}, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -109,8 +105,8 @@ int WebPGetDemuxVersion(void) {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// MemBuffer
|
// MemBuffer
|
||||||
|
|
||||||
static int RemapMemBuffer(MemBuffer* const mem,
|
static int RemapMemBuffer(MemBuffer* const mem, const uint8_t* data,
|
||||||
const uint8_t* data, size_t size) {
|
size_t size) {
|
||||||
if (size < mem->buf_size) return 0; // can't remap to a shorter buffer!
|
if (size < mem->buf_size) return 0; // can't remap to a shorter buffer!
|
||||||
|
|
||||||
mem->buf = data;
|
mem->buf = data;
|
||||||
@@ -118,8 +114,8 @@ static int RemapMemBuffer(MemBuffer* const mem,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int InitMemBuffer(MemBuffer* const mem,
|
static int InitMemBuffer(MemBuffer* const mem, const uint8_t* data,
|
||||||
const uint8_t* data, size_t size) {
|
size_t size) {
|
||||||
memset(mem, 0, sizeof(*mem));
|
memset(mem, 0, sizeof(*mem));
|
||||||
return RemapMemBuffer(mem, data, size);
|
return RemapMemBuffer(mem, data, size);
|
||||||
}
|
}
|
||||||
@@ -195,8 +191,8 @@ static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetFrameInfo(size_t start_offset, size_t size,
|
static void SetFrameInfo(size_t start_offset, size_t size, int frame_num,
|
||||||
int frame_num, int complete,
|
int complete,
|
||||||
const WebPBitstreamFeatures* const features,
|
const WebPBitstreamFeatures* const features,
|
||||||
Frame* const frame) {
|
Frame* const frame) {
|
||||||
frame->img_components[0].offset = start_offset;
|
frame->img_components[0].offset = start_offset;
|
||||||
@@ -214,8 +210,8 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
|||||||
MemBuffer* const mem, Frame* const frame) {
|
MemBuffer* const mem, Frame* const frame) {
|
||||||
int alpha_chunks = 0;
|
int alpha_chunks = 0;
|
||||||
int image_chunks = 0;
|
int image_chunks = 0;
|
||||||
int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE ||
|
int done =
|
||||||
MemDataSize(mem) < min_size);
|
(MemDataSize(mem) < CHUNK_HEADER_SIZE || MemDataSize(mem) < min_size);
|
||||||
ParseStatus status = PARSE_OK;
|
ParseStatus status = PARSE_OK;
|
||||||
|
|
||||||
if (done) return PARSE_NEED_MORE_DATA;
|
if (done) return PARSE_NEED_MORE_DATA;
|
||||||
@@ -232,7 +228,8 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
|||||||
|
|
||||||
payload_size_padded = payload_size + (payload_size & 1);
|
payload_size_padded = payload_size + (payload_size & 1);
|
||||||
payload_available = (payload_size_padded > MemDataSize(mem))
|
payload_available = (payload_size_padded > MemDataSize(mem))
|
||||||
? MemDataSize(mem) : payload_size_padded;
|
? MemDataSize(mem)
|
||||||
|
: payload_size_padded;
|
||||||
chunk_size = CHUNK_HEADER_SIZE + payload_available;
|
chunk_size = CHUNK_HEADER_SIZE + payload_available;
|
||||||
if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
|
if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
|
||||||
if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
|
if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
|
||||||
@@ -258,9 +255,8 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
|||||||
// Extract the bitstream features, tolerating failures when the data
|
// Extract the bitstream features, tolerating failures when the data
|
||||||
// is incomplete.
|
// is incomplete.
|
||||||
WebPBitstreamFeatures features;
|
WebPBitstreamFeatures features;
|
||||||
const VP8StatusCode vp8_status =
|
const VP8StatusCode vp8_status = WebPGetFeatures(
|
||||||
WebPGetFeatures(mem->buf + chunk_start_offset, chunk_size,
|
mem->buf + chunk_start_offset, chunk_size, &features);
|
||||||
&features);
|
|
||||||
if (status == PARSE_NEED_MORE_DATA &&
|
if (status == PARSE_NEED_MORE_DATA &&
|
||||||
vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) {
|
vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) {
|
||||||
return PARSE_NEED_MORE_DATA;
|
return PARSE_NEED_MORE_DATA;
|
||||||
@@ -298,9 +294,8 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
|||||||
// enough data ('min_size') to parse the payload.
|
// enough data ('min_size') to parse the payload.
|
||||||
// Returns PARSE_OK on success with *frame pointing to the new Frame.
|
// Returns PARSE_OK on success with *frame pointing to the new Frame.
|
||||||
// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise.
|
// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise.
|
||||||
static ParseStatus NewFrame(const MemBuffer* const mem,
|
static ParseStatus NewFrame(const MemBuffer* const mem, uint32_t min_size,
|
||||||
uint32_t min_size, uint32_t actual_size,
|
uint32_t actual_size, Frame** frame) {
|
||||||
Frame** frame) {
|
|
||||||
if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
|
if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
|
||||||
if (actual_size < min_size) return PARSE_ERROR;
|
if (actual_size < min_size) return PARSE_ERROR;
|
||||||
if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
|
if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
|
||||||
@@ -311,8 +306,8 @@ static ParseStatus NewFrame(const MemBuffer* const mem,
|
|||||||
|
|
||||||
// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
|
// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
|
||||||
// 'frame_chunk_size' is the previously validated, padded chunk size.
|
// 'frame_chunk_size' is the previously validated, padded chunk size.
|
||||||
static ParseStatus ParseAnimationFrame(
|
static ParseStatus ParseAnimationFrame(WebPDemuxer* const dmux,
|
||||||
WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
|
uint32_t frame_chunk_size) {
|
||||||
const int is_animation = !!(dmux->feature_flags & ANIMATION_FLAG);
|
const int is_animation = !!(dmux->feature_flags & ANIMATION_FLAG);
|
||||||
const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
|
const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
|
||||||
int added_frame = 0;
|
int added_frame = 0;
|
||||||
@@ -320,8 +315,7 @@ static ParseStatus ParseAnimationFrame(
|
|||||||
MemBuffer* const mem = &dmux->mem;
|
MemBuffer* const mem = &dmux->mem;
|
||||||
Frame* frame;
|
Frame* frame;
|
||||||
size_t start_offset;
|
size_t start_offset;
|
||||||
ParseStatus status =
|
ParseStatus status = NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
|
||||||
NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
|
|
||||||
if (status != PARSE_OK) return status;
|
if (status != PARSE_OK) return status;
|
||||||
|
|
||||||
frame->x_offset = 2 * ReadLE24s(mem);
|
frame->x_offset = 2 * ReadLE24s(mem);
|
||||||
@@ -362,8 +356,8 @@ static ParseStatus ParseAnimationFrame(
|
|||||||
// the user to request the payload via a fourcc string. 'size' includes the
|
// the user to request the payload via a fourcc string. 'size' includes the
|
||||||
// header and the unpadded payload size.
|
// header and the unpadded payload size.
|
||||||
// Returns true on success, false otherwise.
|
// Returns true on success, false otherwise.
|
||||||
static int StoreChunk(WebPDemuxer* const dmux,
|
static int StoreChunk(WebPDemuxer* const dmux, size_t start_offset,
|
||||||
size_t start_offset, uint32_t size) {
|
uint32_t size) {
|
||||||
Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk));
|
Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk));
|
||||||
if (chunk == NULL) return 0;
|
if (chunk == NULL) return 0;
|
||||||
|
|
||||||
@@ -647,8 +641,8 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (f->width > 0 && f->height > 0 &&
|
if (f->width > 0 && f->height > 0 &&
|
||||||
!CheckFrameBounds(f, !is_animation,
|
!CheckFrameBounds(f, !is_animation, dmux->canvas_width,
|
||||||
dmux->canvas_width, dmux->canvas_height)) {
|
dmux->canvas_height)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -788,12 +782,18 @@ uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) {
|
|||||||
if (dmux == NULL) return 0;
|
if (dmux == NULL) return 0;
|
||||||
|
|
||||||
switch (feature) {
|
switch (feature) {
|
||||||
case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags;
|
case WEBP_FF_FORMAT_FLAGS:
|
||||||
case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width;
|
return dmux->feature_flags;
|
||||||
case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height;
|
case WEBP_FF_CANVAS_WIDTH:
|
||||||
case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count;
|
return (uint32_t)dmux->canvas_width;
|
||||||
case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor;
|
case WEBP_FF_CANVAS_HEIGHT:
|
||||||
case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames;
|
return (uint32_t)dmux->canvas_height;
|
||||||
|
case WEBP_FF_LOOP_COUNT:
|
||||||
|
return (uint32_t)dmux->loop_count;
|
||||||
|
case WEBP_FF_BACKGROUND_COLOR:
|
||||||
|
return dmux->bgcolor;
|
||||||
|
case WEBP_FF_FRAME_COUNT:
|
||||||
|
return (uint32_t)dmux->num_frames;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -822,8 +822,8 @@ static const uint8_t* GetFramePayload(const uint8_t* const mem_buf,
|
|||||||
// if alpha exists it precedes image, update the size allowing for
|
// if alpha exists it precedes image, update the size allowing for
|
||||||
// intervening chunks.
|
// intervening chunks.
|
||||||
if (alpha->size > 0) {
|
if (alpha->size > 0) {
|
||||||
const size_t inter_size = (image->offset > 0)
|
const size_t inter_size =
|
||||||
? image->offset - (alpha->offset + alpha->size)
|
(image->offset > 0) ? image->offset - (alpha->offset + alpha->size)
|
||||||
: 0;
|
: 0;
|
||||||
start_offset = alpha->offset;
|
start_offset = alpha->offset;
|
||||||
*data_size += alpha->size + inter_size;
|
*data_size += alpha->size + inter_size;
|
||||||
@@ -835,8 +835,7 @@ static const uint8_t* GetFramePayload(const uint8_t* const mem_buf,
|
|||||||
|
|
||||||
// Create a whole 'frame' from VP8 (+ alpha) or lossless.
|
// Create a whole 'frame' from VP8 (+ alpha) or lossless.
|
||||||
static int SynthesizeFrame(const WebPDemuxer* const dmux,
|
static int SynthesizeFrame(const WebPDemuxer* const dmux,
|
||||||
const Frame* const frame,
|
const Frame* const frame, WebPIterator* const iter) {
|
||||||
WebPIterator* const iter) {
|
|
||||||
const uint8_t* const mem_buf = dmux->mem.buf;
|
const uint8_t* const mem_buf = dmux->mem.buf;
|
||||||
size_t payload_size = 0;
|
size_t payload_size = 0;
|
||||||
const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size);
|
const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size);
|
||||||
@@ -891,9 +890,7 @@ int WebPDemuxPrevFrame(WebPIterator* iter) {
|
|||||||
return SetFrame(iter->frame_num - 1, iter);
|
return SetFrame(iter->frame_num - 1, iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPDemuxReleaseIterator(WebPIterator* iter) {
|
void WebPDemuxReleaseIterator(WebPIterator* iter) { (void)iter; }
|
||||||
(void)iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Chunk iteration
|
// Chunk iteration
|
||||||
@@ -944,9 +941,8 @@ static int SetChunk(const char fourcc[4], int chunk_num,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPDemuxGetChunk(const WebPDemuxer* dmux,
|
int WebPDemuxGetChunk(const WebPDemuxer* dmux, const char fourcc[4],
|
||||||
const char fourcc[4], int chunk_num,
|
int chunk_num, WebPChunkIterator* iter) {
|
||||||
WebPChunkIterator* iter) {
|
|
||||||
if (iter == NULL) return 0;
|
if (iter == NULL) return 0;
|
||||||
|
|
||||||
memset(iter, 0, sizeof(*iter));
|
memset(iter, 0, sizeof(*iter));
|
||||||
@@ -972,6 +968,4 @@ int WebPDemuxPrevChunk(WebPChunkIterator* iter) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) {
|
void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { (void)iter; }
|
||||||
(void)iter;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#define USE_TABLES_FOR_ALPHA_MULT 0 // ALTERNATE_CODE
|
#define USE_TABLES_FOR_ALPHA_MULT 0 // ALTERNATE_CODE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define MFIX 24 // 24bit fixed-point arithmetic
|
#define MFIX 24 // 24bit fixed-point arithmetic
|
||||||
@@ -39,8 +38,8 @@ static uint32_t Mult(uint8_t x, uint32_t mult) {
|
|||||||
#if (USE_TABLES_FOR_ALPHA_MULT == 1)
|
#if (USE_TABLES_FOR_ALPHA_MULT == 1)
|
||||||
|
|
||||||
static const uint32_t kMultTables[2][256] = {
|
static const uint32_t kMultTables[2][256] = {
|
||||||
{ // (255u << MFIX) / alpha
|
// (255u << MFIX) / alpha
|
||||||
0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
|
{0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
|
||||||
0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
|
0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
|
||||||
0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
|
0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
|
||||||
0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
|
0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
|
||||||
@@ -82,9 +81,9 @@ static const uint32_t kMultTables[2][256] = {
|
|||||||
0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
|
0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
|
||||||
0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
|
0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
|
||||||
0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
|
0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
|
||||||
0x01030c30, 0x01020612, 0x01010204, 0x01000000 },
|
0x01030c30, 0x01020612, 0x01010204, 0x01000000},
|
||||||
{ // alpha * KINV_255
|
// alpha * KINV_255
|
||||||
0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
|
{0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
|
||||||
0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
|
0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
|
||||||
0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
|
0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
|
||||||
0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
|
0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
|
||||||
@@ -126,8 +125,7 @@ static const uint32_t kMultTables[2][256] = {
|
|||||||
0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
|
0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
|
||||||
0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
|
0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
|
||||||
0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
|
0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
|
||||||
0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }
|
0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff}};
|
||||||
};
|
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
|
static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
|
||||||
return kMultTables[!inverse][a];
|
return kMultTables[!inverse][a];
|
||||||
@@ -162,8 +160,8 @@ void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
|
void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
|
||||||
const uint8_t* WEBP_RESTRICT const alpha,
|
const uint8_t* WEBP_RESTRICT const alpha, int width,
|
||||||
int width, int inverse) {
|
int inverse) {
|
||||||
int x;
|
int x;
|
||||||
for (x = 0; x < width; ++x) {
|
for (x = 0; x < width; ++x) {
|
||||||
const uint32_t a = alpha[x];
|
const uint32_t a = alpha[x];
|
||||||
@@ -184,8 +182,8 @@ void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
|
|||||||
|
|
||||||
void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
|
void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
|
||||||
void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
|
void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
|
||||||
const uint8_t* WEBP_RESTRICT const alpha,
|
const uint8_t* WEBP_RESTRICT const alpha, int width,
|
||||||
int width, int inverse);
|
int inverse);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Generic per-plane calls
|
// Generic per-plane calls
|
||||||
@@ -227,8 +225,8 @@ void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first,
|
static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first, int w, int h,
|
||||||
int w, int h, int stride) {
|
int stride) {
|
||||||
while (h-- > 0) {
|
while (h-- > 0) {
|
||||||
uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
|
uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
|
||||||
const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
|
const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
|
||||||
@@ -265,8 +263,8 @@ static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
|
|||||||
return (x * m) >> 16;
|
return (x * m) >> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444,
|
static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444, int w,
|
||||||
int w, int h, int stride,
|
int h, int stride,
|
||||||
int rg_byte_pos /* 0 or 1 */) {
|
int rg_byte_pos /* 0 or 1 */) {
|
||||||
while (h-- > 0) {
|
while (h-- > 0) {
|
||||||
int i;
|
int i;
|
||||||
@@ -286,8 +284,8 @@ static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444,
|
|||||||
}
|
}
|
||||||
#undef MULTIPLIER
|
#undef MULTIPLIER
|
||||||
|
|
||||||
static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
|
static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444, int w, int h,
|
||||||
int w, int h, int stride) {
|
int stride) {
|
||||||
#if (WEBP_SWAP_16BIT_CSP == 1)
|
#if (WEBP_SWAP_16BIT_CSP == 1)
|
||||||
ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1);
|
ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1);
|
||||||
#else
|
#else
|
||||||
@@ -297,8 +295,8 @@ static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
|
|||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
|
static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
|
||||||
int width, int height,
|
int width, int height, uint8_t* WEBP_RESTRICT dst,
|
||||||
uint8_t* WEBP_RESTRICT dst, int dst_stride) {
|
int dst_stride) {
|
||||||
uint32_t alpha_mask = 0xff;
|
uint32_t alpha_mask = 0xff;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@@ -330,8 +328,8 @@ static void DispatchAlphaToGreen_C(const uint8_t* WEBP_RESTRICT alpha,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
|
static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
|
||||||
int width, int height,
|
int width, int height, uint8_t* WEBP_RESTRICT alpha,
|
||||||
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
|
int alpha_stride) {
|
||||||
uint8_t alpha_mask = 0xff;
|
uint8_t alpha_mask = 0xff;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@@ -357,19 +355,22 @@ static void ExtractGreen_C(const uint32_t* WEBP_RESTRICT argb,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static int HasAlpha8b_C(const uint8_t* src, int length) {
|
static int HasAlpha8b_C(const uint8_t* src, int length) {
|
||||||
while (length-- > 0) if (*src++ != 0xff) return 1;
|
while (length-- > 0)
|
||||||
|
if (*src++ != 0xff) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int HasAlpha32b_C(const uint8_t* src, int length) {
|
static int HasAlpha32b_C(const uint8_t* src, int length) {
|
||||||
int x;
|
int x;
|
||||||
for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1;
|
for (x = 0; length-- > 0; x += 4)
|
||||||
|
if (src[x] != 0xff) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
|
static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
|
||||||
int x;
|
int x;
|
||||||
for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color;
|
for (x = 0; x < length; ++x)
|
||||||
|
if ((src[x] >> 24) == 0) src[x] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -383,8 +384,8 @@ static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
|
|||||||
static void PackARGB_C(const uint8_t* WEBP_RESTRICT a,
|
static void PackARGB_C(const uint8_t* WEBP_RESTRICT a,
|
||||||
const uint8_t* WEBP_RESTRICT r,
|
const uint8_t* WEBP_RESTRICT r,
|
||||||
const uint8_t* WEBP_RESTRICT g,
|
const uint8_t* WEBP_RESTRICT g,
|
||||||
const uint8_t* WEBP_RESTRICT b,
|
const uint8_t* WEBP_RESTRICT b, int len,
|
||||||
int len, uint32_t* WEBP_RESTRICT out) {
|
uint32_t* WEBP_RESTRICT out) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
|
out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
|
||||||
@@ -394,8 +395,8 @@ static void PackARGB_C(const uint8_t* WEBP_RESTRICT a,
|
|||||||
|
|
||||||
static void PackRGB_C(const uint8_t* WEBP_RESTRICT r,
|
static void PackRGB_C(const uint8_t* WEBP_RESTRICT r,
|
||||||
const uint8_t* WEBP_RESTRICT g,
|
const uint8_t* WEBP_RESTRICT g,
|
||||||
const uint8_t* WEBP_RESTRICT b,
|
const uint8_t* WEBP_RESTRICT b, int len, int step,
|
||||||
int len, int step, uint32_t* WEBP_RESTRICT out) {
|
uint32_t* WEBP_RESTRICT out) {
|
||||||
int i, offset = 0;
|
int i, offset = 0;
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
|
out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
|
||||||
@@ -419,8 +420,8 @@ void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g,
|
|||||||
#endif
|
#endif
|
||||||
void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
|
void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
|
||||||
const uint8_t* WEBP_RESTRICT g,
|
const uint8_t* WEBP_RESTRICT g,
|
||||||
const uint8_t* WEBP_RESTRICT b,
|
const uint8_t* WEBP_RESTRICT b, int len, int step,
|
||||||
int len, int step, uint32_t* WEBP_RESTRICT out);
|
uint32_t* WEBP_RESTRICT out);
|
||||||
|
|
||||||
int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
||||||
int (*WebPHasAlpha32b)(const uint8_t* src, int length);
|
int (*WebPHasAlpha32b)(const uint8_t* src, int length);
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
#if defined(WEBP_USE_MIPS_DSP_R2)
|
#if defined(WEBP_USE_MIPS_DSP_R2)
|
||||||
|
|
||||||
static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride,
|
static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride,
|
||||||
int width, int height,
|
int width, int height, uint8_t* dst,
|
||||||
uint8_t* dst, int dst_stride) {
|
int dst_stride) {
|
||||||
uint32_t alpha_mask = 0xffffffff;
|
uint32_t alpha_mask = 0xffffffff;
|
||||||
int i, j, temp0;
|
int i, j, temp0;
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride,
|
|||||||
for (i = 0; i < (width >> 2); ++i) {
|
for (i = 0; i < (width >> 2); ++i) {
|
||||||
int temp1, temp2, temp3;
|
int temp1, temp2, temp3;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], 0(%[palpha]) \n\t"
|
"ulw %[temp0], 0(%[palpha]) \n\t"
|
||||||
"addiu %[palpha], %[palpha], 4 \n\t"
|
"addiu %[palpha], %[palpha], 4 \n\t"
|
||||||
"addiu %[pdst], %[pdst], 16 \n\t"
|
"addiu %[pdst], %[pdst], 16 \n\t"
|
||||||
@@ -40,47 +40,43 @@ static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride,
|
|||||||
"sb %[temp1], -12(%[pdst]) \n\t"
|
"sb %[temp1], -12(%[pdst]) \n\t"
|
||||||
"sb %[temp2], -8(%[pdst]) \n\t"
|
"sb %[temp2], -8(%[pdst]) \n\t"
|
||||||
"sb %[temp3], -4(%[pdst]) \n\t"
|
"sb %[temp3], -4(%[pdst]) \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst),
|
[temp3] "=&r"(temp3), [palpha] "+r"(palpha), [pdst] "+r"(pdst),
|
||||||
[alpha_mask]"+r"(alpha_mask)
|
[alpha_mask] "+r"(alpha_mask)
|
||||||
:
|
:
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (width & 3); ++i) {
|
for (i = 0; i < (width & 3); ++i) {
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"lbu %[temp0], 0(%[palpha]) \n\t"
|
"lbu %[temp0], 0(%[palpha]) \n\t"
|
||||||
"addiu %[palpha], %[palpha], 1 \n\t"
|
"addiu %[palpha], %[palpha], 1 \n\t"
|
||||||
"sb %[temp0], 0(%[pdst]) \n\t"
|
"sb %[temp0], 0(%[pdst]) \n\t"
|
||||||
"and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
|
"and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
|
||||||
"addiu %[pdst], %[pdst], 4 \n\t"
|
"addiu %[pdst], %[pdst], 4 \n\t"
|
||||||
: [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst),
|
: [temp0] "=&r"(temp0), [palpha] "+r"(palpha), [pdst] "+r"(pdst),
|
||||||
[alpha_mask]"+r"(alpha_mask)
|
[alpha_mask] "+r"(alpha_mask)
|
||||||
:
|
:
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
alpha += alpha_stride;
|
alpha += alpha_stride;
|
||||||
dst += dst_stride;
|
dst += dst_stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ext %[temp0], %[alpha_mask], 0, 16 \n\t"
|
"ext %[temp0], %[alpha_mask], 0, 16 \n\t"
|
||||||
"srl %[alpha_mask], %[alpha_mask], 16 \n\t"
|
"srl %[alpha_mask], %[alpha_mask], 16 \n\t"
|
||||||
"and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
|
"and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
|
||||||
"ext %[temp0], %[alpha_mask], 0, 8 \n\t"
|
"ext %[temp0], %[alpha_mask], 0, 8 \n\t"
|
||||||
"srl %[alpha_mask], %[alpha_mask], 8 \n\t"
|
"srl %[alpha_mask], %[alpha_mask], 8 \n\t"
|
||||||
"and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
|
"and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask)
|
: [temp0] "=&r"(temp0), [alpha_mask] "+r"(alpha_mask)
|
||||||
:
|
:);
|
||||||
);
|
|
||||||
|
|
||||||
return (alpha_mask != 0xff);
|
return (alpha_mask != 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width,
|
static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width, int inverse) {
|
||||||
int inverse) {
|
|
||||||
int x;
|
int x;
|
||||||
const uint32_t c_00ffffff = 0x00ffffffu;
|
const uint32_t c_00ffffff = 0x00ffffffu;
|
||||||
const uint32_t c_ff000000 = 0xff000000u;
|
const uint32_t c_ff000000 = 0xff000000u;
|
||||||
@@ -93,7 +89,7 @@ static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width,
|
|||||||
ptr[x] = 0;
|
ptr[x] = 0;
|
||||||
} else {
|
} else {
|
||||||
int temp0, temp1, temp2, temp3, alpha;
|
int temp0, temp1, temp2, temp3, alpha;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"srl %[alpha], %[argb], 24 \n\t"
|
"srl %[alpha], %[argb], 24 \n\t"
|
||||||
"replv.qb %[temp0], %[alpha] \n\t"
|
"replv.qb %[temp0], %[alpha] \n\t"
|
||||||
"and %[temp0], %[temp0], %[c_00ffffff] \n\t"
|
"and %[temp0], %[temp0], %[c_00ffffff] \n\t"
|
||||||
@@ -112,13 +108,12 @@ static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width,
|
|||||||
"addu %[temp1], %[temp1], %[c_8000080] \n\t"
|
"addu %[temp1], %[temp1], %[c_8000080] \n\t"
|
||||||
"precrq.ph.w %[temp3], %[argb], %[temp3] \n\t"
|
"precrq.ph.w %[temp3], %[argb], %[temp3] \n\t"
|
||||||
"precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
|
"precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [alpha]"=&r"(alpha)
|
[temp3] "=&r"(temp3), [alpha] "=&r"(alpha)
|
||||||
: [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff),
|
: [inverse] "r"(inverse), [c_00ffffff] "r"(c_00ffffff),
|
||||||
[c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080),
|
[c_8000000] "r"(c_8000000), [c_8000080] "r"(c_8000080),
|
||||||
[c_ff000000]"r"(c_ff000000), [argb]"r"(argb)
|
[c_ff000000] "r"(c_ff000000), [argb] "r"(argb)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
ptr[x] = temp1;
|
ptr[x] = temp1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +128,7 @@ static void PackARGB_MIPSdspR2(const uint8_t* a, const uint8_t* r,
|
|||||||
const int rest = len & 1;
|
const int rest = len & 1;
|
||||||
const uint32_t* const loop_end = out + len - rest;
|
const uint32_t* const loop_end = out + len - rest;
|
||||||
const int step = 4;
|
const int step = 4;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"xor %[offset], %[offset], %[offset] \n\t"
|
"xor %[offset], %[offset], %[offset] \n\t"
|
||||||
"beq %[loop_end], %[out], 0f \n\t"
|
"beq %[loop_end], %[out], 0f \n\t"
|
||||||
"2: \n\t"
|
"2: \n\t"
|
||||||
@@ -159,12 +154,11 @@ static void PackARGB_MIPSdspR2(const uint8_t* a, const uint8_t* r,
|
|||||||
"precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
|
"precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
|
||||||
"sw %[temp0], 0(%[out]) \n\t"
|
"sw %[temp0], 0(%[out]) \n\t"
|
||||||
"1: \n\t"
|
"1: \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out)
|
[temp3] "=&r"(temp3), [offset] "=&r"(offset), [out] "+&r"(out)
|
||||||
: [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
|
: [a] "r"(a), [r] "r"(r), [g] "r"(g), [b] "r"(b), [step] "r"(step),
|
||||||
[loop_end]"r"(loop_end), [rest]"r"(rest)
|
[loop_end] "r"(loop_end), [rest] "r"(rest)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#endif // WORDS_BIGENDIAN
|
#endif // WORDS_BIGENDIAN
|
||||||
|
|
||||||
@@ -175,7 +169,7 @@ static void PackRGB_MIPSdspR2(const uint8_t* r, const uint8_t* g,
|
|||||||
const int rest = len & 1;
|
const int rest = len & 1;
|
||||||
const int a = 0xff;
|
const int a = 0xff;
|
||||||
const uint32_t* const loop_end = out + len - rest;
|
const uint32_t* const loop_end = out + len - rest;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"xor %[offset], %[offset], %[offset] \n\t"
|
"xor %[offset], %[offset], %[offset] \n\t"
|
||||||
"beq %[loop_end], %[out], 0f \n\t"
|
"beq %[loop_end], %[out], 0f \n\t"
|
||||||
"2: \n\t"
|
"2: \n\t"
|
||||||
@@ -199,12 +193,11 @@ static void PackRGB_MIPSdspR2(const uint8_t* r, const uint8_t* g,
|
|||||||
"precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t"
|
"precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t"
|
||||||
"sw %[temp0], 0(%[out]) \n\t"
|
"sw %[temp0], 0(%[out]) \n\t"
|
||||||
"1: \n\t"
|
"1: \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[offset]"=&r"(offset), [out]"+&r"(out)
|
[offset] "=&r"(offset), [out] "+&r"(out)
|
||||||
: [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
|
: [a] "r"(a), [r] "r"(r), [g] "r"(g), [b] "r"(b), [step] "r"(step),
|
||||||
[loop_end]"r"(loop_end), [rest]"r"(rest)
|
[loop_end] "r"(loop_end), [rest] "r"(rest)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
#define MULTIPLIER(a) ((a) * 0x8081)
|
#define MULTIPLIER(a) ((a) * 0x8081)
|
||||||
#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
|
#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
|
||||||
|
|
||||||
#define MULTIPLY_BY_ALPHA(V, ALPHA, OTHER) do { \
|
#define MULTIPLY_BY_ALPHA(V, ALPHA, OTHER) \
|
||||||
|
do { \
|
||||||
const uint8x8_t alpha = (V).val[(ALPHA)]; \
|
const uint8x8_t alpha = (V).val[(ALPHA)]; \
|
||||||
const uint16x8_t r1 = vmull_u8((V).val[1], alpha); \
|
const uint16x8_t r1 = vmull_u8((V).val[1], alpha); \
|
||||||
const uint16x8_t g1 = vmull_u8((V).val[2], alpha); \
|
const uint16x8_t g1 = vmull_u8((V).val[2], alpha); \
|
||||||
@@ -37,10 +38,10 @@
|
|||||||
(V).val[1] = vshrn_n_u16(r3, 8); \
|
(V).val[1] = vshrn_n_u16(r3, 8); \
|
||||||
(V).val[2] = vshrn_n_u16(g3, 8); \
|
(V).val[2] = vshrn_n_u16(g3, 8); \
|
||||||
(V).val[(OTHER)] = vshrn_n_u16(b3, 8); \
|
(V).val[(OTHER)] = vshrn_n_u16(b3, 8); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
|
static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first, int w,
|
||||||
int w, int h, int stride) {
|
int h, int stride) {
|
||||||
const uint16x8_t kOne = vdupq_n_u16(1u);
|
const uint16x8_t kOne = vdupq_n_u16(1u);
|
||||||
while (h-- > 0) {
|
while (h-- > 0) {
|
||||||
uint32_t* const rgbx = (uint32_t*)rgba;
|
uint32_t* const rgbx = (uint32_t*)rgba;
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
#if defined(WEBP_USE_SSE2)
|
#if defined(WEBP_USE_SSE2)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -204,7 +204,8 @@ static void ExtractGreen_SSE2(const uint32_t* WEBP_RESTRICT argb,
|
|||||||
// immediate in the _mm_shufflexx_epi16() instruction. We really need a macro.
|
// immediate in the _mm_shufflexx_epi16() instruction. We really need a macro.
|
||||||
// We use: v / 255 = (v * 0x8081) >> 23, where v = alpha * {r,g,b} is a 16bit
|
// We use: v / 255 = (v * 0x8081) >> 23, where v = alpha * {r,g,b} is a 16bit
|
||||||
// value.
|
// value.
|
||||||
#define APPLY_ALPHA(RGBX, SHUFFLE) do { \
|
#define APPLY_ALPHA(RGBX, SHUFFLE) \
|
||||||
|
do { \
|
||||||
const __m128i argb0 = _mm_loadu_si128((const __m128i*)&(RGBX)); \
|
const __m128i argb0 = _mm_loadu_si128((const __m128i*)&(RGBX)); \
|
||||||
const __m128i argb1_lo = _mm_unpacklo_epi8(argb0, zero); \
|
const __m128i argb1_lo = _mm_unpacklo_epi8(argb0, zero); \
|
||||||
const __m128i argb1_hi = _mm_unpackhi_epi8(argb0, zero); \
|
const __m128i argb1_hi = _mm_unpackhi_epi8(argb0, zero); \
|
||||||
@@ -223,10 +224,10 @@ static void ExtractGreen_SSE2(const uint32_t* WEBP_RESTRICT argb,
|
|||||||
const __m128i A2_hi = _mm_srli_epi16(A1_hi, 7); \
|
const __m128i A2_hi = _mm_srli_epi16(A1_hi, 7); \
|
||||||
const __m128i A3 = _mm_packus_epi16(A2_lo, A2_hi); \
|
const __m128i A3 = _mm_packus_epi16(A2_lo, A2_hi); \
|
||||||
_mm_storeu_si128((__m128i*)&(RGBX), A3); \
|
_mm_storeu_si128((__m128i*)&(RGBX), A3); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first,
|
static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first, int w,
|
||||||
int w, int h, int stride) {
|
int h, int stride) {
|
||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
const __m128i kMult = _mm_set1_epi16((short)0x8081);
|
const __m128i kMult = _mm_set1_epi16((short)0x8081);
|
||||||
const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0);
|
const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0);
|
||||||
@@ -273,7 +274,8 @@ static int HasAlpha8b_SSE2(const uint8_t* src, int length) {
|
|||||||
const int mask = _mm_movemask_epi8(bits);
|
const int mask = _mm_movemask_epi8(bits);
|
||||||
if (mask != 0xffff) return 1;
|
if (mask != 0xffff) return 1;
|
||||||
}
|
}
|
||||||
for (; i < length; ++i) if (src[i] != 0xff) return 1;
|
for (; i < length; ++i)
|
||||||
|
if (src[i] != 0xff) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +314,8 @@ static int HasAlpha32b_SSE2(const uint8_t* src, int length) {
|
|||||||
const int mask = _mm_movemask_epi8(bits);
|
const int mask = _mm_movemask_epi8(bits);
|
||||||
if (mask != 0xffff) return 1;
|
if (mask != 0xffff) return 1;
|
||||||
}
|
}
|
||||||
for (; i <= length; i += 4) if (src[i] != 0xff) return 1;
|
for (; i <= length; i += 4)
|
||||||
|
if (src[i] != 0xff) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +337,8 @@ static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) {
|
|||||||
_mm_storeu_si128((__m128i*)(src + i + 0), _mm_or_si128(d0, e0));
|
_mm_storeu_si128((__m128i*)(src + i + 0), _mm_or_si128(d0, e0));
|
||||||
_mm_storeu_si128((__m128i*)(src + i + 4), _mm_or_si128(d1, e1));
|
_mm_storeu_si128((__m128i*)(src + i + 4), _mm_or_si128(d1, e1));
|
||||||
}
|
}
|
||||||
for (; i < length; ++i) if ((src[i] >> 24) == 0) src[i] = color;
|
for (; i < length; ++i)
|
||||||
|
if ((src[i] >> 24) == 0) src[i] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -369,8 +373,8 @@ static void MultARGBRow_SSE2(uint32_t* const ptr, int width, int inverse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void MultRow_SSE2(uint8_t* WEBP_RESTRICT const ptr,
|
static void MultRow_SSE2(uint8_t* WEBP_RESTRICT const ptr,
|
||||||
const uint8_t* WEBP_RESTRICT const alpha,
|
const uint8_t* WEBP_RESTRICT const alpha, int width,
|
||||||
int width, int inverse) {
|
int inverse) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
if (!inverse) {
|
if (!inverse) {
|
||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
// Author: Skal (pascal.massimino@gmail.com)
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
#if defined(WEBP_USE_SSE41)
|
#if defined(WEBP_USE_SSE41)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
@@ -35,14 +35,14 @@ static int ExtractAlpha_SSE41(const uint8_t* WEBP_RESTRICT argb,
|
|||||||
// 'src[4 * width - 4]', because we don't know if alpha is the first or the
|
// 'src[4 * width - 4]', because we don't know if alpha is the first or the
|
||||||
// last byte of the quadruplet.
|
// last byte of the quadruplet.
|
||||||
const int limit = (width - 1) & ~15;
|
const int limit = (width - 1) & ~15;
|
||||||
const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
|
const __m128i kCstAlpha0 =
|
||||||
-1, -1, -1, -1, 12, 8, 4, 0);
|
_mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 8, 4, 0);
|
||||||
const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
|
const __m128i kCstAlpha1 =
|
||||||
12, 8, 4, 0, -1, -1, -1, -1);
|
_mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 12, 8, 4, 0, -1, -1, -1, -1);
|
||||||
const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0,
|
const __m128i kCstAlpha2 =
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1);
|
_mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1);
|
||||||
const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1,
|
const __m128i kCstAlpha3 =
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1);
|
_mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
|
||||||
for (j = 0; j < height; ++j) {
|
for (j = 0; j < height; ++j) {
|
||||||
const __m128i* src = (const __m128i*)argb;
|
const __m128i* src = (const __m128i*)argb;
|
||||||
for (i = 0; i < limit; i += 16) {
|
for (i = 0; i < limit; i += 16) {
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ static WEBP_INLINE void VP8PlanarTo24b_SSE41(
|
|||||||
|
|
||||||
// Process R.
|
// Process R.
|
||||||
{
|
{
|
||||||
const __m128i shuff0 = _mm_set_epi8(
|
const __m128i shuff0 =
|
||||||
5, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0);
|
_mm_set_epi8(5, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0);
|
||||||
const __m128i shuff1 = _mm_set_epi8(
|
const __m128i shuff1 = _mm_set_epi8(-1, 10, -1, -1, 9, -1, -1, 8, -1, -1, 7,
|
||||||
-1, 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1);
|
-1, -1, 6, -1, -1);
|
||||||
const __m128i shuff2 = _mm_set_epi8(
|
const __m128i shuff2 = _mm_set_epi8(-1, -1, 15, -1, -1, 14, -1, -1, 13, -1,
|
||||||
-1, -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1);
|
-1, 12, -1, -1, 11, -1);
|
||||||
WEBP_SSE41_SHUFF(R, in0, in1)
|
WEBP_SSE41_SHUFF(R, in0, in1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,23 +57,23 @@ static WEBP_INLINE void VP8PlanarTo24b_SSE41(
|
|||||||
{
|
{
|
||||||
// Same as before, just shifted to the left by one and including the right
|
// Same as before, just shifted to the left by one and including the right
|
||||||
// padding.
|
// padding.
|
||||||
const __m128i shuff0 = _mm_set_epi8(
|
const __m128i shuff0 =
|
||||||
-1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1);
|
_mm_set_epi8(-1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1);
|
||||||
const __m128i shuff1 = _mm_set_epi8(
|
const __m128i shuff1 =
|
||||||
10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5);
|
_mm_set_epi8(10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5);
|
||||||
const __m128i shuff2 = _mm_set_epi8(
|
const __m128i shuff2 = _mm_set_epi8(-1, 15, -1, -1, 14, -1, -1, 13, -1, -1,
|
||||||
-1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1);
|
12, -1, -1, 11, -1, -1);
|
||||||
WEBP_SSE41_SHUFF(G, in2, in3)
|
WEBP_SSE41_SHUFF(G, in2, in3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process B.
|
// Process B.
|
||||||
{
|
{
|
||||||
const __m128i shuff0 = _mm_set_epi8(
|
const __m128i shuff0 =
|
||||||
-1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1, -1);
|
_mm_set_epi8(-1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1, -1);
|
||||||
const __m128i shuff1 = _mm_set_epi8(
|
const __m128i shuff1 =
|
||||||
-1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5, -1);
|
_mm_set_epi8(-1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5, -1);
|
||||||
const __m128i shuff2 = _mm_set_epi8(
|
const __m128i shuff2 = _mm_set_epi8(15, -1, -1, 14, -1, -1, 13, -1, -1, 12,
|
||||||
15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1, 10);
|
-1, -1, 11, -1, -1, 10);
|
||||||
WEBP_SSE41_SHUFF(B, in4, in5)
|
WEBP_SSE41_SHUFF(B, in4, in5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
479
src/dsp/cost.c
479
src/dsp/cost.c
@@ -14,42 +14,37 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
#include "src/enc/cost_enc.h"
|
#include "src/enc/cost_enc.h"
|
||||||
#include "src/enc/vp8i_enc.h"
|
#include "src/enc/vp8i_enc.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Boolean-cost cost table
|
// Boolean-cost cost table
|
||||||
|
|
||||||
const uint16_t VP8EntropyCost[256] = {
|
const uint16_t VP8EntropyCost[256] = {
|
||||||
1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216,
|
1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216, 1178, 1152,
|
||||||
1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951,
|
1110, 1076, 1061, 1024, 1024, 992, 968, 951, 939, 911, 896, 878,
|
||||||
939, 911, 896, 878, 871, 854, 838, 820, 811, 794,
|
871, 854, 838, 820, 811, 794, 786, 768, 768, 752, 740, 732,
|
||||||
786, 768, 768, 752, 740, 732, 720, 709, 704, 690,
|
720, 709, 704, 690, 683, 672, 666, 655, 647, 640, 631, 622,
|
||||||
683, 672, 666, 655, 647, 640, 631, 622, 615, 607,
|
615, 607, 598, 592, 586, 576, 572, 564, 559, 555, 547, 541,
|
||||||
598, 592, 586, 576, 572, 564, 559, 555, 547, 541,
|
534, 528, 522, 512, 512, 504, 500, 494, 488, 483, 477, 473,
|
||||||
534, 528, 522, 512, 512, 504, 500, 494, 488, 483,
|
467, 461, 458, 452, 448, 443, 438, 434, 427, 424, 419, 415,
|
||||||
477, 473, 467, 461, 458, 452, 448, 443, 438, 434,
|
410, 406, 403, 399, 394, 390, 384, 384, 377, 374, 370, 366,
|
||||||
427, 424, 419, 415, 410, 406, 403, 399, 394, 390,
|
362, 359, 355, 351, 347, 342, 342, 336, 333, 330, 326, 323,
|
||||||
384, 384, 377, 374, 370, 366, 362, 359, 355, 351,
|
320, 316, 312, 308, 305, 302, 299, 296, 293, 288, 287, 283,
|
||||||
347, 342, 342, 336, 333, 330, 326, 323, 320, 316,
|
280, 277, 274, 272, 268, 266, 262, 256, 256, 256, 251, 248,
|
||||||
312, 308, 305, 302, 299, 296, 293, 288, 287, 283,
|
245, 242, 240, 237, 234, 232, 228, 226, 223, 221, 218, 216,
|
||||||
280, 277, 274, 272, 268, 266, 262, 256, 256, 256,
|
214, 211, 208, 205, 203, 201, 198, 196, 192, 191, 188, 187,
|
||||||
251, 248, 245, 242, 240, 237, 234, 232, 228, 226,
|
183, 181, 179, 176, 175, 171, 171, 168, 165, 163, 160, 159,
|
||||||
223, 221, 218, 216, 214, 211, 208, 205, 203, 201,
|
156, 154, 152, 150, 148, 146, 144, 142, 139, 138, 135, 133,
|
||||||
198, 196, 192, 191, 188, 187, 183, 181, 179, 176,
|
131, 128, 128, 125, 123, 121, 119, 117, 115, 113, 111, 110,
|
||||||
175, 171, 171, 168, 165, 163, 160, 159, 156, 154,
|
107, 105, 103, 102, 100, 98, 96, 94, 92, 91, 89, 86,
|
||||||
152, 150, 148, 146, 144, 142, 139, 138, 135, 133,
|
86, 83, 82, 80, 77, 76, 74, 73, 71, 69, 67, 66,
|
||||||
131, 128, 128, 125, 123, 121, 119, 117, 115, 113,
|
64, 63, 61, 59, 57, 55, 54, 52, 51, 49, 47, 46,
|
||||||
111, 110, 107, 105, 103, 102, 100, 98, 96, 94,
|
44, 43, 41, 40, 38, 36, 35, 33, 32, 30, 29, 27,
|
||||||
92, 91, 89, 86, 86, 83, 82, 80, 77, 76,
|
25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9,
|
||||||
74, 73, 71, 69, 67, 66, 64, 63, 61, 59,
|
7, 6, 4, 3};
|
||||||
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
|
// Level cost tables
|
||||||
@@ -57,263 +52,177 @@ const uint16_t VP8EntropyCost[256] = {
|
|||||||
// fixed costs for coding levels, deduce from the coding tree.
|
// fixed costs for coding levels, deduce from the coding tree.
|
||||||
// This is only the part that doesn't depend on the probability state.
|
// This is only the part that doesn't depend on the probability state.
|
||||||
const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = {
|
const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = {
|
||||||
0, 256, 256, 256, 256, 432, 618, 630,
|
0, 256, 256, 256, 256, 432, 618, 630, 731, 640, 640, 828,
|
||||||
731, 640, 640, 828, 901, 948, 1021, 1101,
|
901, 948, 1021, 1101, 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
|
||||||
1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
|
1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497, 1540, 1570, 1613, 1280,
|
||||||
1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497,
|
1295, 1317, 1332, 1358, 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532,
|
||||||
1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358,
|
1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679, 1694, 1716, 1731, 1775,
|
||||||
1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532,
|
1790, 1812, 1827, 1853, 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759,
|
||||||
1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679,
|
1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832, 1838, 1847, 1853, 1878,
|
||||||
1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853,
|
1884, 1893, 1899, 1910, 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983,
|
||||||
1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759,
|
1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059, 2065, 2074, 2080, 2100,
|
||||||
1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832,
|
2106, 2115, 2121, 2132, 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210,
|
||||||
1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910,
|
2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283, 2289, 2298, 2304, 2168,
|
||||||
1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983,
|
2174, 2183, 2189, 2200, 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273,
|
||||||
1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059,
|
2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351, 2357, 2366, 2372, 2392,
|
||||||
2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132,
|
2398, 2407, 2413, 2424, 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500,
|
||||||
2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210,
|
2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573, 2579, 2588, 2594, 2619,
|
||||||
2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283,
|
2625, 2634, 2640, 2651, 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724,
|
||||||
2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200,
|
2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572, 2578, 2587, 2593, 2613,
|
||||||
2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273,
|
2619, 2628, 2634, 2645, 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723,
|
||||||
2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351,
|
2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796, 2802, 2811, 2817, 2840,
|
||||||
2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424,
|
2846, 2855, 2861, 2872, 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945,
|
||||||
2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500,
|
2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023, 3029, 3038, 3044, 3064,
|
||||||
2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573,
|
3070, 3079, 3085, 3096, 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013,
|
||||||
2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651,
|
3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086, 3092, 3101, 3107, 3132,
|
||||||
2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724,
|
3138, 3147, 3153, 3164, 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237,
|
||||||
2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572,
|
3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313, 3319, 3328, 3334, 3354,
|
||||||
2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645,
|
3360, 3369, 3375, 3386, 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464,
|
||||||
2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723,
|
3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537, 3543, 3552, 3558, 2816,
|
||||||
2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796,
|
2822, 2831, 2837, 2848, 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921,
|
||||||
2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872,
|
2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999, 3005, 3014, 3020, 3040,
|
||||||
2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945,
|
3046, 3055, 3061, 3072, 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148,
|
||||||
2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023,
|
3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221, 3227, 3236, 3242, 3267,
|
||||||
3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096,
|
3273, 3282, 3288, 3299, 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372,
|
||||||
3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013,
|
3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289, 3295, 3304, 3310, 3330,
|
||||||
3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086,
|
3336, 3345, 3351, 3362, 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440,
|
||||||
3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164,
|
3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513, 3519, 3528, 3534, 3557,
|
||||||
3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237,
|
3563, 3572, 3578, 3589, 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662,
|
||||||
3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313,
|
3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740, 3746, 3755, 3761, 3781,
|
||||||
3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386,
|
3787, 3796, 3802, 3813, 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661,
|
||||||
3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464,
|
3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734, 3740, 3749, 3755, 3780,
|
||||||
3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537,
|
3786, 3795, 3801, 3812, 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885,
|
||||||
3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848,
|
3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961, 3967, 3976, 3982, 4002,
|
||||||
2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921,
|
4008, 4017, 4023, 4034, 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112,
|
||||||
2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999,
|
4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185, 4191, 4200, 4206, 4070,
|
||||||
3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072,
|
4076, 4085, 4091, 4102, 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175,
|
||||||
3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148,
|
4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253, 4259, 4268, 4274, 4294,
|
||||||
3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221,
|
4300, 4309, 4315, 4326, 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402,
|
||||||
3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299,
|
4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475, 4481, 4490, 4496, 4521,
|
||||||
3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372,
|
4527, 4536, 4542, 4553, 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626,
|
||||||
3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289,
|
4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547, 3553, 3562, 3568, 3588,
|
||||||
3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362,
|
3594, 3603, 3609, 3620, 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
|
||||||
3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440,
|
3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, 3777, 3786, 3792, 3815,
|
||||||
3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513,
|
3821, 3830, 3836, 3847, 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
|
||||||
3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589,
|
3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, 4004, 4013, 4019, 4039,
|
||||||
3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662,
|
4045, 4054, 4060, 4071, 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
|
||||||
3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740,
|
3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, 4067, 4076, 4082, 4107,
|
||||||
3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813,
|
4113, 4122, 4128, 4139, 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
|
||||||
3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661,
|
4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, 4294, 4303, 4309, 4329,
|
||||||
3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734,
|
4335, 4344, 4350, 4361, 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
|
||||||
3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812,
|
4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, 4518, 4527, 4533, 4328,
|
||||||
3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885,
|
4334, 4343, 4349, 4360, 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
|
||||||
3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961,
|
4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, 4517, 4526, 4532, 4552,
|
||||||
3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034,
|
4558, 4567, 4573, 4584, 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
|
||||||
4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112,
|
4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, 4739, 4748, 4754, 4779,
|
||||||
4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185,
|
4785, 4794, 4800, 4811, 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
|
||||||
4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102,
|
4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, 4807, 4816, 4822, 4842,
|
||||||
4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175,
|
4848, 4857, 4863, 4874, 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
|
||||||
4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253,
|
4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, 5031, 5040, 5046, 5069,
|
||||||
4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326,
|
5075, 5084, 5090, 5101, 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
|
||||||
4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402,
|
5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, 5258, 5267, 5273, 5293,
|
||||||
4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475,
|
5299, 5308, 5314, 5325, 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
|
||||||
4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553,
|
4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, 4715, 4724, 4730, 4755,
|
||||||
4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626,
|
4761, 4770, 4776, 4787, 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
|
||||||
4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547,
|
4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, 4942, 4951, 4957, 4977,
|
||||||
3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
|
4983, 4992, 4998, 5009, 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
|
||||||
3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
|
5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, 5166, 5175, 5181, 5045,
|
||||||
3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
|
5051, 5060, 5066, 5077, 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
|
||||||
3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
|
5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, 5234, 5243, 5249, 5269,
|
||||||
3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
|
5275, 5284, 5290, 5301, 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
|
||||||
3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
|
5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, 5456, 5465, 5471, 5496,
|
||||||
4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
|
5502, 5511, 5517, 5528, 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
|
||||||
4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
|
5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, 5455, 5464, 5470, 5490,
|
||||||
3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
|
5496, 5505, 5511, 5522, 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
|
||||||
4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
|
5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, 5679, 5688, 5694, 5717,
|
||||||
4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
|
5723, 5732, 5738, 5749, 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
|
||||||
4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
|
5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, 5906, 5915, 5921, 5941,
|
||||||
4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
|
5947, 5956, 5962, 5973, 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
|
||||||
4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
|
5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, 5969, 5978, 5984, 6009,
|
||||||
4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
|
6015, 6024, 6030, 6041, 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
|
||||||
4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
|
6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, 6196, 6205, 6211, 6231,
|
||||||
4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
|
6237, 6246, 6252, 6263, 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
|
||||||
4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
|
6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, 6420, 6429, 6435, 3515,
|
||||||
4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
|
3521, 3530, 3536, 3547, 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
|
||||||
4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
|
3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, 3704, 3713, 3719, 3739,
|
||||||
4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
|
3745, 3754, 3760, 3771, 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
|
||||||
4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
|
3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, 3926, 3935, 3941, 3966,
|
||||||
4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
|
3972, 3981, 3987, 3998, 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
|
||||||
4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
|
4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, 3994, 4003, 4009, 4029,
|
||||||
4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
|
4035, 4044, 4050, 4061, 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
|
||||||
4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
|
4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, 4218, 4227, 4233, 4256,
|
||||||
4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
|
4262, 4271, 4277, 4288, 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
|
||||||
5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
|
4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, 4445, 4454, 4460, 4480,
|
||||||
5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
|
4486, 4495, 4501, 4512, 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
|
||||||
5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
|
4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, 4439, 4448, 4454, 4479,
|
||||||
5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
|
4485, 4494, 4500, 4511, 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
|
||||||
5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
|
4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, 4666, 4675, 4681, 4701,
|
||||||
4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
|
4707, 4716, 4722, 4733, 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
|
||||||
4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
|
4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, 4890, 4899, 4905, 4769,
|
||||||
4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
|
4775, 4784, 4790, 4801, 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
|
||||||
4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
|
4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, 4958, 4967, 4973, 4993,
|
||||||
4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
|
4999, 5008, 5014, 5025, 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
|
||||||
5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
|
5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, 5180, 5189, 5195, 5220,
|
||||||
5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
|
5226, 5235, 5241, 5252, 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
|
||||||
5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
|
5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, 4642, 4651, 4657, 4677,
|
||||||
5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
|
4683, 4692, 4698, 4709, 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
|
||||||
5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
|
4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, 4866, 4875, 4881, 4904,
|
||||||
5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
|
4910, 4919, 4925, 4936, 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
|
||||||
5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
|
5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, 5093, 5102, 5108, 5128,
|
||||||
5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
|
5134, 5143, 5149, 5160, 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
|
||||||
5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
|
5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, 5156, 5165, 5171, 5196,
|
||||||
5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
|
5202, 5211, 5217, 5228, 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
|
||||||
5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
|
5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, 5383, 5392, 5398, 5418,
|
||||||
5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
|
5424, 5433, 5439, 5450, 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
|
||||||
5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
|
5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, 5607, 5616, 5622, 5417,
|
||||||
5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
|
5423, 5432, 5438, 5449, 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
|
||||||
5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
|
5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, 5606, 5615, 5621, 5641,
|
||||||
5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
|
5647, 5656, 5662, 5673, 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
|
||||||
5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
|
5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, 5828, 5837, 5843, 5868,
|
||||||
5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
|
5874, 5883, 5889, 5900, 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
|
||||||
5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
|
5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, 5896, 5905, 5911, 5931,
|
||||||
5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
|
5937, 5946, 5952, 5963, 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
|
||||||
5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
|
6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, 6120, 6129, 6135, 6158,
|
||||||
6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
|
6164, 6173, 6179, 6190, 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
|
||||||
6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
|
6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, 6347, 6356, 6362, 6382,
|
||||||
6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
|
6388, 6397, 6403, 6414, 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335,
|
||||||
6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
|
5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408, 5414, 5423, 5429, 5454,
|
||||||
6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
|
5460, 5469, 5475, 5486, 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559,
|
||||||
6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547,
|
5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635, 5641, 5650, 5656, 5676,
|
||||||
3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
|
5682, 5691, 5697, 5708, 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786,
|
||||||
3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
|
5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859, 5865, 5874, 5880, 5744,
|
||||||
3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
|
5750, 5759, 5765, 5776, 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849,
|
||||||
3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
|
5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927, 5933, 5942, 5948, 5968,
|
||||||
3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
|
5974, 5983, 5989, 6000, 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076,
|
||||||
3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
|
6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149, 6155, 6164, 6170, 6195,
|
||||||
4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
|
6201, 6210, 6216, 6227, 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300,
|
||||||
4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
|
6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148, 6154, 6163, 6169, 6189,
|
||||||
3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
|
6195, 6204, 6210, 6221, 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299,
|
||||||
4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
|
6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372, 6378, 6387, 6393, 6416,
|
||||||
4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
|
6422, 6431, 6437, 6448, 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521,
|
||||||
4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
|
6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599, 6605, 6614, 6620, 6640,
|
||||||
4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
|
6646, 6655, 6661, 6672, 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589,
|
||||||
4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
|
6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662, 6668, 6677, 6683, 6708,
|
||||||
4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
|
6714, 6723, 6729, 6740, 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813,
|
||||||
4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
|
6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889, 6895, 6904, 6910, 6930,
|
||||||
4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
|
6936, 6945, 6951, 6962, 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040,
|
||||||
4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
|
7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113, 7119, 7128, 7134, 6392,
|
||||||
4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
|
6398, 6407, 6413, 6424, 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497,
|
||||||
4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
|
6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575, 6581, 6590, 6596, 6616,
|
||||||
4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
|
6622, 6631, 6637, 6648, 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724,
|
||||||
4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
|
6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797, 6803, 6812, 6818, 6843,
|
||||||
4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
|
6849, 6858, 6864, 6875, 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948,
|
||||||
4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
|
6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865, 6871, 6880, 6886, 6906,
|
||||||
4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
|
6912, 6921, 6927, 6938, 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016,
|
||||||
4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
|
7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089, 7095, 7104, 7110, 7133,
|
||||||
4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
|
7139, 7148, 7154, 7165, 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238,
|
||||||
5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
|
7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316, 7322, 7331, 7337, 7357,
|
||||||
5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
|
7363, 7372, 7378, 7389, 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237,
|
||||||
5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
|
7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310, 7316, 7325, 7331, 7356,
|
||||||
5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
|
7362, 7371, 7377, 7388, 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461,
|
||||||
5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
|
7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537, 7543, 7552, 7558, 7578,
|
||||||
4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
|
7584, 7593, 7599, 7610, 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688,
|
||||||
4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
|
7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761};
|
||||||
4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
|
|
||||||
4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
|
|
||||||
4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
|
|
||||||
5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
|
|
||||||
5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
|
|
||||||
5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
|
|
||||||
5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
|
|
||||||
5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
|
|
||||||
5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
|
|
||||||
5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
|
|
||||||
5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
|
|
||||||
5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
|
|
||||||
5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
|
|
||||||
5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
|
|
||||||
5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
|
|
||||||
5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
|
|
||||||
5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
|
|
||||||
5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
|
|
||||||
5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
|
|
||||||
5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
|
|
||||||
5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
|
|
||||||
5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
|
|
||||||
5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
|
|
||||||
5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
|
|
||||||
6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
|
|
||||||
6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
|
|
||||||
6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
|
|
||||||
6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
|
|
||||||
6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
|
|
||||||
6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335,
|
|
||||||
5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408,
|
|
||||||
5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486,
|
|
||||||
5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559,
|
|
||||||
5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635,
|
|
||||||
5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708,
|
|
||||||
5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786,
|
|
||||||
5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859,
|
|
||||||
5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776,
|
|
||||||
5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849,
|
|
||||||
5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927,
|
|
||||||
5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000,
|
|
||||||
6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076,
|
|
||||||
6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149,
|
|
||||||
6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227,
|
|
||||||
6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300,
|
|
||||||
6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148,
|
|
||||||
6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221,
|
|
||||||
6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299,
|
|
||||||
6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372,
|
|
||||||
6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448,
|
|
||||||
6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521,
|
|
||||||
6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599,
|
|
||||||
6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672,
|
|
||||||
6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589,
|
|
||||||
6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662,
|
|
||||||
6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740,
|
|
||||||
6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813,
|
|
||||||
6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889,
|
|
||||||
6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962,
|
|
||||||
6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040,
|
|
||||||
7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113,
|
|
||||||
7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424,
|
|
||||||
6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497,
|
|
||||||
6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575,
|
|
||||||
6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648,
|
|
||||||
6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724,
|
|
||||||
6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797,
|
|
||||||
6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875,
|
|
||||||
6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948,
|
|
||||||
6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865,
|
|
||||||
6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938,
|
|
||||||
6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016,
|
|
||||||
7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089,
|
|
||||||
7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165,
|
|
||||||
7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238,
|
|
||||||
7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316,
|
|
||||||
7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389,
|
|
||||||
7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237,
|
|
||||||
7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310,
|
|
||||||
7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388,
|
|
||||||
7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461,
|
|
||||||
7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537,
|
|
||||||
7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610,
|
|
||||||
7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688,
|
|
||||||
7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Tables for level coding
|
// Tables for level coding
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ static int GetResidualCost_MIPS32(int ctx0, const VP8Residual* const res) {
|
|||||||
return VP8BitCost(0, p0);
|
return VP8BitCost(0, p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"subu %[temp1], %[res_last], %[n] \n\t"
|
"subu %[temp1], %[res_last], %[n] \n\t"
|
||||||
@@ -72,14 +72,14 @@ static int GetResidualCost_MIPS32(int ctx0, const VP8Residual* const res) {
|
|||||||
" lw %[t], 0(%[t]) \n\t"
|
" lw %[t], 0(%[t]) \n\t"
|
||||||
"2: \n\t"
|
"2: \n\t"
|
||||||
".set pop \n\t"
|
".set pop \n\t"
|
||||||
: [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg),
|
: [cost] "+&r"(cost), [t] "+&r"(t), [n] "+&r"(n), [v_reg] "=&r"(v_reg),
|
||||||
[ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0),
|
[ctx_reg] "=&r"(ctx_reg), [p_costs] "+&r"(p_costs),
|
||||||
[temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs)
|
[temp0] "=&r"(temp0), [temp1] "=&r"(temp1),
|
||||||
: [const_2]"r"(const_2), [const_max_level]"r"(const_max_level),
|
[res_coeffs] "+&r"(res_coeffs)
|
||||||
[VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last),
|
: [const_2] "r"(const_2), [const_max_level] "r"(const_max_level),
|
||||||
[inc_p_costs]"r"(inc_p_costs)
|
[VP8LevelFixedCosts] "r"(VP8LevelFixedCosts), [res_last] "r"(res_last),
|
||||||
: "memory"
|
[inc_p_costs] "r"(inc_p_costs)
|
||||||
);
|
: "memory");
|
||||||
|
|
||||||
// Last coefficient is always non-zero
|
// Last coefficient is always non-zero
|
||||||
{
|
{
|
||||||
@@ -102,7 +102,7 @@ static void SetResidualCoeffs_MIPS32(const int16_t* WEBP_RESTRICT const coeffs,
|
|||||||
int temp0, temp1, temp2, n, n1;
|
int temp0, temp1, temp2, n, n1;
|
||||||
assert(res->first == 0 || coeffs[0] == 0);
|
assert(res->first == 0 || coeffs[0] == 0);
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"addiu %[p_coeffs], %[p_coeffs], 28 \n\t"
|
"addiu %[p_coeffs], %[p_coeffs], 28 \n\t"
|
||||||
@@ -127,12 +127,10 @@ static void SetResidualCoeffs_MIPS32(const int16_t* WEBP_RESTRICT const coeffs,
|
|||||||
" addiu %[p_coeffs], %[p_coeffs], -4 \n\t"
|
" addiu %[p_coeffs], %[p_coeffs], -4 \n\t"
|
||||||
"2: \n\t"
|
"2: \n\t"
|
||||||
".set pop \n\t"
|
".set pop \n\t"
|
||||||
: [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0),
|
: [p_coeffs] "+&r"(p_coeffs), [temp0] "=&r"(temp0), [temp1] "=&r"(temp1),
|
||||||
[temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
[temp2] "=&r"(temp2), [n] "=&r"(n), [n1] "=&r"(n1)
|
||||||
[n]"=&r"(n), [n1]"=&r"(n1)
|
|
||||||
:
|
:
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
res->last = temp2;
|
res->last = temp2;
|
||||||
res->coeffs = coeffs;
|
res->coeffs = coeffs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,14 @@ static int GetResidualCost_MIPSdspR2(int ctx0, const VP8Residual* const res) {
|
|||||||
return VP8BitCost(0, p0);
|
return VP8BitCost(0, p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"subu %[temp1], %[res_last], %[n] \n\t"
|
"subu %[temp1], %[res_last], %[n] \n\t"
|
||||||
"blez %[temp1], 2f \n\t"
|
"blez %[temp1], 2f \n\t"
|
||||||
" nop \n\t"
|
" nop \n\t"
|
||||||
"1: \n\t"
|
"1: "
|
||||||
|
"\n\t"
|
||||||
"sll %[temp0], %[n], 1 \n\t"
|
"sll %[temp0], %[n], 1 \n\t"
|
||||||
"lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t"
|
"lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t"
|
||||||
"addiu %[n], %[n], 1 \n\t"
|
"addiu %[n], %[n], 1 \n\t"
|
||||||
@@ -65,16 +66,16 @@ static int GetResidualCost_MIPSdspR2(int ctx0, const VP8Residual* const res) {
|
|||||||
"addu %[cost], %[cost], %[temp0] \n\t"
|
"addu %[cost], %[cost], %[temp0] \n\t"
|
||||||
"bne %[n], %[res_last], 1b \n\t"
|
"bne %[n], %[res_last], 1b \n\t"
|
||||||
" lw %[t], 0(%[t]) \n\t"
|
" lw %[t], 0(%[t]) \n\t"
|
||||||
"2: \n\t"
|
"2: "
|
||||||
|
"\n\t"
|
||||||
".set pop \n\t"
|
".set pop \n\t"
|
||||||
: [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg),
|
: [cost] "+&r"(cost), [t] "+&r"(t), [n] "+&r"(n), [v_reg] "=&r"(v_reg),
|
||||||
[ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0),
|
[ctx_reg] "=&r"(ctx_reg), [p_costs] "+&r"(p_costs),
|
||||||
[temp1]"=&r"(temp1)
|
[temp0] "=&r"(temp0), [temp1] "=&r"(temp1)
|
||||||
: [const_2]"r"(const_2), [const_max_level]"r"(const_max_level),
|
: [const_2] "r"(const_2), [const_max_level] "r"(const_max_level),
|
||||||
[VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last),
|
[VP8LevelFixedCosts] "r"(VP8LevelFixedCosts), [res_last] "r"(res_last),
|
||||||
[res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs)
|
[res_coeffs] "r"(res_coeffs), [inc_p_costs] "r"(inc_p_costs)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
|
|
||||||
// Last coefficient is always non-zero
|
// Last coefficient is always non-zero
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
#include "src/dsp/neon.h"
|
#include "src/dsp/neon.h"
|
||||||
#include "src/enc/cost_enc.h"
|
#include "src/enc/cost_enc.h"
|
||||||
|
|
||||||
static const uint8_t position[16] = { 1, 2, 3, 4, 5, 6, 7, 8,
|
static const uint8_t position[16] = {1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
9, 10, 11, 12, 13, 14, 15, 16 };
|
9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
|
|
||||||
static void SetResidualCoeffs_NEON(const int16_t* WEBP_RESTRICT const coeffs,
|
static void SetResidualCoeffs_NEON(const int16_t* WEBP_RESTRICT const coeffs,
|
||||||
VP8Residual* WEBP_RESTRICT const res) {
|
VP8Residual* WEBP_RESTRICT const res) {
|
||||||
|
|||||||
@@ -14,15 +14,14 @@
|
|||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
|
|
||||||
#if defined(WEBP_USE_SSE2)
|
#if defined(WEBP_USE_SSE2)
|
||||||
|
#include <assert.h>
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/enc/cost_enc.h"
|
#include "src/enc/cost_enc.h"
|
||||||
#include "src/enc/vp8i_enc.h"
|
#include "src/enc/vp8i_enc.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/utils/utils.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -33,18 +33,19 @@
|
|||||||
// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC.
|
// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC.
|
||||||
#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__)
|
#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__)
|
||||||
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"mov %%ebx, %%edi\n"
|
"mov %%ebx, %%edi\n"
|
||||||
"cpuid\n"
|
"cpuid\n"
|
||||||
"xchg %%edi, %%ebx\n"
|
"xchg %%edi, %%ebx\n"
|
||||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||||
|
"=d"(cpu_info[3])
|
||||||
: "a"(info_type), "c"(0));
|
: "a"(info_type), "c"(0));
|
||||||
}
|
}
|
||||||
#elif defined(__i386__) || defined(__x86_64__)
|
#elif defined(__i386__) || defined(__x86_64__)
|
||||||
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
||||||
__asm__ volatile (
|
__asm__ volatile("cpuid\n"
|
||||||
"cpuid\n"
|
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
"=d"(cpu_info[3])
|
||||||
: "a"(info_type), "c"(0));
|
: "a"(info_type), "c"(0));
|
||||||
}
|
}
|
||||||
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
|
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
|
||||||
@@ -67,13 +68,13 @@ static WEBP_INLINE uint64_t xgetbv(void) {
|
|||||||
const uint32_t ecx = 0;
|
const uint32_t ecx = 0;
|
||||||
uint32_t eax, edx;
|
uint32_t eax, edx;
|
||||||
// Use the raw opcode for xgetbv for compatibility with older toolchains.
|
// Use the raw opcode for xgetbv for compatibility with older toolchains.
|
||||||
__asm__ volatile (
|
__asm__ volatile(".byte 0x0f, 0x01, 0xd0\n"
|
||||||
".byte 0x0f, 0x01, 0xd0\n"
|
: "=a"(eax), "=d"(edx)
|
||||||
: "=a"(eax), "=d"(edx) : "c" (ecx));
|
: "c"(ecx));
|
||||||
return ((uint64_t)edx << 32) | eax;
|
return ((uint64_t)edx << 32) | eax;
|
||||||
}
|
}
|
||||||
#elif (defined(_M_X64) || defined(_M_IX86)) && \
|
#elif (defined(_M_X64) || defined(_M_IX86)) && defined(_MSC_FULL_VER) && \
|
||||||
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
|
_MSC_FULL_VER >= 160040219 // >= VS2010 SP1
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#define xgetbv() _xgetbv(0)
|
#define xgetbv() _xgetbv(0)
|
||||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||||
@@ -241,7 +242,6 @@ static int mipsCPUInfo(CPUFeature feature) {
|
|||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
|
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
|
||||||
VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
|
VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
|
||||||
|
|||||||
@@ -192,6 +192,7 @@
|
|||||||
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
||||||
#include <pthread.h> // NOLINT
|
#include <pthread.h> // NOLINT
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define WEBP_DSP_INIT(func) \
|
#define WEBP_DSP_INIT(func) \
|
||||||
do { \
|
do { \
|
||||||
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
|
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
|
||||||
@@ -202,7 +203,9 @@
|
|||||||
func##_last_cpuinfo_used = VP8GetCPUInfo; \
|
func##_last_cpuinfo_used = VP8GetCPUInfo; \
|
||||||
(void)pthread_mutex_unlock(&func##_lock); \
|
(void)pthread_mutex_unlock(&func##_lock); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
|
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
|
||||||
|
// clang-format off
|
||||||
#define WEBP_DSP_INIT(func) \
|
#define WEBP_DSP_INIT(func) \
|
||||||
do { \
|
do { \
|
||||||
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
|
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
|
||||||
@@ -211,6 +214,7 @@
|
|||||||
func(); \
|
func(); \
|
||||||
func##_last_cpuinfo_used = VP8GetCPUInfo; \
|
func##_last_cpuinfo_used = VP8GetCPUInfo; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
||||||
|
|
||||||
// Defines an Init + helper function that control multiple initialization of
|
// Defines an Init + helper function that control multiple initialization of
|
||||||
|
|||||||
@@ -34,13 +34,14 @@ static WEBP_INLINE uint8_t clip_8b(int v) {
|
|||||||
#define STORE(x, y, v) \
|
#define STORE(x, y, v) \
|
||||||
dst[(x) + (y) * BPS] = clip_8b(dst[(x) + (y) * BPS] + ((v) >> 3))
|
dst[(x) + (y) * BPS] = clip_8b(dst[(x) + (y) * BPS] + ((v) >> 3))
|
||||||
|
|
||||||
#define STORE2(y, dc, d, c) do { \
|
#define STORE2(y, dc, d, c) \
|
||||||
|
do { \
|
||||||
const int DC = (dc); \
|
const int DC = (dc); \
|
||||||
STORE(0, y, DC + (d)); \
|
STORE(0, y, DC + (d)); \
|
||||||
STORE(1, y, DC + (c)); \
|
STORE(1, y, DC + (c)); \
|
||||||
STORE(2, y, DC - (c)); \
|
STORE(2, y, DC - (c)); \
|
||||||
STORE(3, y, DC - (d)); \
|
STORE(3, y, DC - (d)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
static void TransformOne_C(const int16_t* WEBP_RESTRICT in,
|
static void TransformOne_C(const int16_t* WEBP_RESTRICT in,
|
||||||
@@ -150,8 +151,8 @@ static void TransformWHT_C(const int16_t* WEBP_RESTRICT in,
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
const int a0 = in[0 + i] + in[12 + i];
|
const int a0 = in[0 + i] + in[12 + i];
|
||||||
const int a1 = in[4 + i] + in[ 8 + i];
|
const int a1 = in[4 + i] + in[8 + i];
|
||||||
const int a2 = in[4 + i] - in[ 8 + i];
|
const int a2 = in[4 + i] - in[8 + i];
|
||||||
const int a3 = in[0 + i] - in[12 + i];
|
const int a3 = in[0 + i] - in[12 + i];
|
||||||
tmp[0 + i] = a0 + a1;
|
tmp[0 + i] = a0 + a1;
|
||||||
tmp[8 + i] = a0 - a1;
|
tmp[8 + i] = a0 - a1;
|
||||||
@@ -164,7 +165,7 @@ static void TransformWHT_C(const int16_t* WEBP_RESTRICT in,
|
|||||||
const int a1 = tmp[1 + i * 4] + tmp[2 + 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 a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
|
||||||
const int a3 = dc - tmp[3 + i * 4];
|
const int a3 = dc - tmp[3 + i * 4];
|
||||||
out[ 0] = (a0 + a1) >> 3;
|
out[0] = (a0 + a1) >> 3;
|
||||||
out[16] = (a3 + a2) >> 3;
|
out[16] = (a3 + a2) >> 3;
|
||||||
out[32] = (a0 - a1) >> 3;
|
out[32] = (a0 - a1) >> 3;
|
||||||
out[48] = (a3 - a2) >> 3;
|
out[48] = (a3 - a2) >> 3;
|
||||||
@@ -268,9 +269,9 @@ static void VE4_C(uint8_t* dst) { // vertical
|
|||||||
const uint8_t* top = dst - BPS;
|
const uint8_t* top = dst - BPS;
|
||||||
const uint8_t vals[4] = {
|
const uint8_t vals[4] = {
|
||||||
AVG3(top[-1], top[0], top[1]),
|
AVG3(top[-1], top[0], top[1]),
|
||||||
AVG3(top[ 0], top[1], top[2]),
|
AVG3(top[0], top[1], top[2]),
|
||||||
AVG3(top[ 1], top[2], top[3]),
|
AVG3(top[1], top[2], top[3]),
|
||||||
AVG3(top[ 2], top[3], top[4])
|
AVG3(top[2], top[3], top[4]),
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
@@ -393,8 +394,7 @@ static void HU4_C(uint8_t* dst) { // Horizontal-Up
|
|||||||
DST(1, 0) = AVG3(I, J, K);
|
DST(1, 0) = AVG3(I, J, K);
|
||||||
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
||||||
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
||||||
DST(3, 2) = DST(2, 2) =
|
DST(3, 2) = DST(2, 2) = DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
||||||
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HD4_C(uint8_t* dst) { // Horizontal-Down
|
static void HD4_C(uint8_t* dst) { // Horizontal-Down
|
||||||
@@ -493,46 +493,46 @@ VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES];
|
|||||||
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
||||||
// 4 pixels in, 2 pixels out
|
// 4 pixels in, 2 pixels out
|
||||||
static WEBP_INLINE void DoFilter2_C(uint8_t* p, int step) {
|
static WEBP_INLINE void DoFilter2_C(uint8_t* p, int step) {
|
||||||
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[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 a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892]
|
||||||
const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15]
|
const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15]
|
||||||
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
||||||
p[-step] = VP8kclip1[p0 + a2];
|
p[-step] = VP8kclip1[p0 + a2];
|
||||||
p[ 0] = VP8kclip1[q0 - a1];
|
p[0] = VP8kclip1[q0 - a1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 pixels in, 4 pixels out
|
// 4 pixels in, 4 pixels out
|
||||||
static WEBP_INLINE void DoFilter4_C(uint8_t* p, int step) {
|
static WEBP_INLINE void DoFilter4_C(uint8_t* p, int step) {
|
||||||
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
|
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
|
||||||
const int a = 3 * (q0 - p0);
|
const int a = 3 * (q0 - p0);
|
||||||
const int a1 = VP8ksclip2[(a + 4) >> 3];
|
const int a1 = VP8ksclip2[(a + 4) >> 3];
|
||||||
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
||||||
const int a3 = (a1 + 1) >> 1;
|
const int a3 = (a1 + 1) >> 1;
|
||||||
p[-2*step] = VP8kclip1[p1 + a3];
|
p[-2 * step] = VP8kclip1[p1 + a3];
|
||||||
p[- step] = VP8kclip1[p0 + a2];
|
p[-step] = VP8kclip1[p0 + a2];
|
||||||
p[ 0] = VP8kclip1[q0 - a1];
|
p[0] = VP8kclip1[q0 - a1];
|
||||||
p[ step] = VP8kclip1[q1 - a3];
|
p[step] = VP8kclip1[q1 - a3];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6 pixels in, 6 pixels out
|
// 6 pixels in, 6 pixels out
|
||||||
static WEBP_INLINE void DoFilter6_C(uint8_t* p, int step) {
|
static WEBP_INLINE void DoFilter6_C(uint8_t* p, int step) {
|
||||||
const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-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 q0 = p[0], q1 = p[step], q2 = p[2 * step];
|
||||||
const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
|
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]
|
// 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 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 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
|
const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
|
||||||
p[-3*step] = VP8kclip1[p2 + a3];
|
p[-3 * step] = VP8kclip1[p2 + a3];
|
||||||
p[-2*step] = VP8kclip1[p1 + a2];
|
p[-2 * step] = VP8kclip1[p1 + a2];
|
||||||
p[- step] = VP8kclip1[p0 + a1];
|
p[-step] = VP8kclip1[p0 + a1];
|
||||||
p[ 0] = VP8kclip1[q0 - a1];
|
p[0] = VP8kclip1[q0 - a1];
|
||||||
p[ step] = VP8kclip1[q1 - a2];
|
p[step] = VP8kclip1[q1 - a2];
|
||||||
p[ 2*step] = VP8kclip1[q2 - a3];
|
p[2 * step] = VP8kclip1[q2 - a3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int Hev(const uint8_t* p, int step, int thresh) {
|
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];
|
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
|
||||||
return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh);
|
return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh);
|
||||||
}
|
}
|
||||||
#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
||||||
@@ -545,8 +545,8 @@ static WEBP_INLINE int NeedsFilter_C(const uint8_t* p, int step, int t) {
|
|||||||
#endif // !WEBP_NEON_OMIT_C_CODE
|
#endif // !WEBP_NEON_OMIT_C_CODE
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
||||||
static WEBP_INLINE int NeedsFilter2_C(const uint8_t* p,
|
static WEBP_INLINE int NeedsFilter2_C(const uint8_t* p, int step, int t,
|
||||||
int step, int t, int it) {
|
int it) {
|
||||||
const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step];
|
const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step];
|
||||||
const int p0 = p[-step], q0 = p[0];
|
const int p0 = p[-step], q0 = p[0];
|
||||||
const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
|
const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
|
||||||
@@ -602,9 +602,8 @@ static void SimpleHFilter16i_C(uint8_t* p, int stride, int thresh) {
|
|||||||
// Complex In-loop filtering (Paragraph 15.3)
|
// Complex In-loop filtering (Paragraph 15.3)
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
||||||
static WEBP_INLINE void FilterLoop26_C(uint8_t* p,
|
static WEBP_INLINE void FilterLoop26_C(uint8_t* p, int hstride, int vstride,
|
||||||
int hstride, int vstride, int size,
|
int size, int thresh, int ithresh,
|
||||||
int thresh, int ithresh,
|
|
||||||
int hev_thresh) {
|
int hev_thresh) {
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
while (size-- > 0) {
|
while (size-- > 0) {
|
||||||
@@ -619,9 +618,8 @@ static WEBP_INLINE void FilterLoop26_C(uint8_t* p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void FilterLoop24_C(uint8_t* p,
|
static WEBP_INLINE void FilterLoop24_C(uint8_t* p, int hstride, int vstride,
|
||||||
int hstride, int vstride, int size,
|
int size, int thresh, int ithresh,
|
||||||
int thresh, int ithresh,
|
|
||||||
int hev_thresh) {
|
int hev_thresh) {
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
while (size-- > 0) {
|
while (size-- > 0) {
|
||||||
@@ -639,19 +637,19 @@ static WEBP_INLINE void FilterLoop24_C(uint8_t* p,
|
|||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
// on macroblock edges
|
// on macroblock edges
|
||||||
static void VFilter16_C(uint8_t* p, int stride,
|
static void VFilter16_C(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
FilterLoop26_C(p, stride, 1, 16, thresh, ithresh, hev_thresh);
|
FilterLoop26_C(p, stride, 1, 16, thresh, ithresh, hev_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16_C(uint8_t* p, int stride,
|
static void HFilter16_C(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
FilterLoop26_C(p, 1, stride, 16, thresh, ithresh, hev_thresh);
|
FilterLoop26_C(p, 1, stride, 16, thresh, ithresh, hev_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// on three inner edges
|
// on three inner edges
|
||||||
static void VFilter16i_C(uint8_t* p, int stride,
|
static void VFilter16i_C(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 3; k > 0; --k) {
|
for (k = 3; k > 0; --k) {
|
||||||
p += 4 * stride;
|
p += 4 * stride;
|
||||||
@@ -661,8 +659,8 @@ static void VFilter16i_C(uint8_t* p, int stride,
|
|||||||
#endif // !WEBP_NEON_OMIT_C_CODE
|
#endif // !WEBP_NEON_OMIT_C_CODE
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
||||||
static void HFilter16i_C(uint8_t* p, int stride,
|
static void HFilter16i_C(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 3; k > 0; --k) {
|
for (k = 3; k > 0; --k) {
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
// Author: Skal (pascal.massimino@gmail.com)
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
// define to 0 to have run-time table initialization
|
// define to 0 to have run-time table initialization
|
||||||
#if !defined(USE_STATIC_TABLES)
|
#if !defined(USE_STATIC_TABLES)
|
||||||
@@ -65,8 +65,7 @@ static const uint8_t abs0[255 + 255 + 1] = {
|
|||||||
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
|
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
|
||||||
0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
|
0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
|
||||||
0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||||
0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t sclip1[1020 + 1020 + 1] = {
|
static const uint8_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,
|
||||||
@@ -238,8 +237,7 @@ static const uint8_t sclip1[1020 + 1020 + 1] = {
|
|||||||
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||||
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||||
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||||
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 uint8_t sclip2[112 + 112 + 1] = {
|
static const uint8_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,
|
||||||
@@ -260,8 +258,7 @@ static const uint8_t sclip2[112 + 112 + 1] = {
|
|||||||
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] = {
|
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,
|
||||||
@@ -327,8 +324,7 @@ static const uint8_t clip1[255 + 511 + 1] = {
|
|||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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
|
#else
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
|
|||||||
const int a1 = VP8ksclip2[(a + 4) >> 3];
|
const int a1 = VP8ksclip2[(a + 4) >> 3];
|
||||||
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
||||||
p[-step] = VP8kclip1[p0 + a2];
|
p[-step] = VP8kclip1[p0 + a2];
|
||||||
p[ 0] = VP8kclip1[q0 - a1];
|
p[0] = VP8kclip1[q0 - a1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 pixels in, 4 pixels out
|
// 4 pixels in, 4 pixels out
|
||||||
@@ -44,9 +44,9 @@ static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
|
|||||||
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
const int a2 = VP8ksclip2[(a + 3) >> 3];
|
||||||
const int a3 = (a1 + 1) >> 1;
|
const int a3 = (a1 + 1) >> 1;
|
||||||
p[-2 * step] = VP8kclip1[p1 + a3];
|
p[-2 * step] = VP8kclip1[p1 + a3];
|
||||||
p[- step] = VP8kclip1[p0 + a2];
|
p[-step] = VP8kclip1[p0 + a2];
|
||||||
p[ 0] = VP8kclip1[q0 - a1];
|
p[0] = VP8kclip1[q0 - a1];
|
||||||
p[ step] = VP8kclip1[q1 - a3];
|
p[step] = VP8kclip1[q1 - a3];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6 pixels in, 6 pixels out
|
// 6 pixels in, 6 pixels out
|
||||||
@@ -60,10 +60,10 @@ static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
|
|||||||
const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * 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[-3 * step] = VP8kclip1[p2 + a3];
|
||||||
p[-2 * step] = VP8kclip1[p1 + a2];
|
p[-2 * step] = VP8kclip1[p1 + a2];
|
||||||
p[- step] = VP8kclip1[p0 + a1];
|
p[-step] = VP8kclip1[p0 + a1];
|
||||||
p[ 0] = VP8kclip1[q0 - a1];
|
p[0] = VP8kclip1[q0 - a1];
|
||||||
p[ step] = VP8kclip1[q1 - a2];
|
p[step] = VP8kclip1[q1 - a2];
|
||||||
p[ 2 * step] = VP8kclip1[q2 - a3];
|
p[2 * step] = VP8kclip1[q2 - a3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
|
static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
|
||||||
@@ -76,8 +76,8 @@ static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) {
|
|||||||
return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t);
|
return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int needs_filter2(const uint8_t* p,
|
static WEBP_INLINE int needs_filter2(const uint8_t* p, int step, int t,
|
||||||
int step, int t, int it) {
|
int it) {
|
||||||
const int p3 = p[-4 * step], p2 = p[-3 * step];
|
const int p3 = p[-4 * step], p2 = p[-3 * step];
|
||||||
const int p1 = p[-2 * step], p0 = p[-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];
|
const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
|
||||||
@@ -89,9 +89,9 @@ static WEBP_INLINE int needs_filter2(const uint8_t* p,
|
|||||||
abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it;
|
abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void FilterLoop26(uint8_t* p,
|
static WEBP_INLINE void FilterLoop26(uint8_t* p, int hstride, int vstride,
|
||||||
int hstride, int vstride, int size,
|
int size, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
while (size-- > 0) {
|
while (size-- > 0) {
|
||||||
if (needs_filter2(p, hstride, thresh2, ithresh)) {
|
if (needs_filter2(p, hstride, thresh2, ithresh)) {
|
||||||
@@ -105,9 +105,9 @@ static WEBP_INLINE void FilterLoop26(uint8_t* p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void FilterLoop24(uint8_t* p,
|
static WEBP_INLINE void FilterLoop24(uint8_t* p, int hstride, int vstride,
|
||||||
int hstride, int vstride, int size,
|
int size, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
while (size-- > 0) {
|
while (size-- > 0) {
|
||||||
if (needs_filter2(p, hstride, thresh2, ithresh)) {
|
if (needs_filter2(p, hstride, thresh2, ithresh)) {
|
||||||
@@ -122,13 +122,13 @@ static WEBP_INLINE void FilterLoop24(uint8_t* p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on macroblock edges
|
// on macroblock edges
|
||||||
static void VFilter16(uint8_t* p, int stride,
|
static void VFilter16(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
|
FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16(uint8_t* p, int stride,
|
static void HFilter16(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
|
FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,8 +158,8 @@ static void HFilter8i(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on three inner edges
|
// on three inner edges
|
||||||
static void VFilter16i(uint8_t* p, int stride,
|
static void VFilter16i(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 3; k > 0; --k) {
|
for (k = 3; k > 0; --k) {
|
||||||
p += 4 * stride;
|
p += 4 * stride;
|
||||||
@@ -167,8 +167,8 @@ static void VFilter16i(uint8_t* p, int stride,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16i(uint8_t* p, int stride,
|
static void HFilter16i(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 3; k > 0; --k) {
|
for (k = 3; k > 0; --k) {
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static void TransformDC(const int16_t* WEBP_RESTRICT in,
|
|||||||
uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
|
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst,
|
LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 1, 2, 3,
|
0, 1, 2, 3,
|
||||||
@@ -56,7 +56,7 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
||||||
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
|
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ins %[c4], %[d4], 16, 16 \n\t"
|
"ins %[c4], %[d4], 16, 16 \n\t"
|
||||||
"replv.ph %[temp1], %[a] \n\t"
|
"replv.ph %[temp1], %[a] \n\t"
|
||||||
"replv.ph %[temp4], %[d1] \n\t"
|
"replv.ph %[temp4], %[d1] \n\t"
|
||||||
@@ -88,7 +88,7 @@ static void TransformOne(const int16_t* WEBP_RESTRICT in,
|
|||||||
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
||||||
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
|
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp1], 0(%[in]) \n\t"
|
"ulw %[temp1], 0(%[in]) \n\t"
|
||||||
"ulw %[temp2], 16(%[in]) \n\t"
|
"ulw %[temp2], 16(%[in]) \n\t"
|
||||||
LOAD_IN_X2(temp5, temp6, 24, 26)
|
LOAD_IN_X2(temp5, temp6, 24, 26)
|
||||||
@@ -159,14 +159,14 @@ static void TransformTwo(const int16_t* WEBP_RESTRICT in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void FilterLoop26(uint8_t* p,
|
static WEBP_INLINE void FilterLoop26(uint8_t* p, int hstride, int vstride,
|
||||||
int hstride, int vstride, int size,
|
int size, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
||||||
int temp10, temp11, temp12, temp13, temp14, temp15;
|
int temp10, temp11, temp12, temp13, temp14, temp15;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"1: \n\t"
|
"1: \n\t"
|
||||||
@@ -284,29 +284,28 @@ static WEBP_INLINE void FilterLoop26(uint8_t* p,
|
|||||||
"bgtz %[size], 1b \n\t"
|
"bgtz %[size], 1b \n\t"
|
||||||
" addu %[p], %[p], %[vstride] \n\t"
|
" addu %[p], %[p], %[vstride] \n\t"
|
||||||
".set pop \n\t"
|
".set pop \n\t"
|
||||||
: [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3),
|
: [temp1] "=&r"(temp1), [temp2] "=&r"(temp2), [temp3] "=&r"(temp3),
|
||||||
[temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6),
|
[temp4] "=&r"(temp4), [temp5] "=&r"(temp5), [temp6] "=&r"(temp6),
|
||||||
[temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9),
|
[temp7] "=&r"(temp7), [temp8] "=&r"(temp8), [temp9] "=&r"(temp9),
|
||||||
[temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12),
|
[temp10] "=&r"(temp10), [temp11] "=&r"(temp11), [temp12] "=&r"(temp12),
|
||||||
[temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15),
|
[temp13] "=&r"(temp13), [temp14] "=&r"(temp14), [temp15] "=&r"(temp15),
|
||||||
[size]"+&r"(size), [p]"+&r"(p)
|
[size] "+&r"(size), [p] "+&r"(p)
|
||||||
: [hstride]"r"(hstride), [thresh2]"r"(thresh2),
|
: [hstride] "r"(hstride), [thresh2] "r"(thresh2), [ithresh] "r"(ithresh),
|
||||||
[ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh),
|
[vstride] "r"(vstride), [hev_thresh] "r"(hev_thresh),
|
||||||
[VP8kclip1]"r"(VP8kclip1)
|
[VP8kclip1] "r"(VP8kclip1)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void FilterLoop24(uint8_t* p,
|
static WEBP_INLINE void FilterLoop24(uint8_t* p, int hstride, int vstride,
|
||||||
int hstride, int vstride, int size,
|
int size, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int p0, q0, p1, q1, p2, q2, p3, q3;
|
int p0, q0, p1, q1, p2, q2, p3, q3;
|
||||||
int step1, step2, temp1, temp2, temp3, temp4;
|
int step1, step2, temp1, temp2, temp3, temp4;
|
||||||
uint8_t* pTemp0;
|
uint8_t* pTemp0;
|
||||||
uint8_t* pTemp1;
|
uint8_t* pTemp1;
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"bltz %[size], 3f \n\t"
|
"bltz %[size], 3f \n\t"
|
||||||
@@ -413,27 +412,26 @@ static WEBP_INLINE void FilterLoop24(uint8_t* p,
|
|||||||
" addu %[p], %[p], %[vstride] \n\t"
|
" addu %[p], %[p], %[vstride] \n\t"
|
||||||
"3: \n\t"
|
"3: \n\t"
|
||||||
".set pop \n\t"
|
".set pop \n\t"
|
||||||
: [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1),
|
: [p0] "=&r"(p0), [q0] "=&r"(q0), [p1] "=&r"(p1), [q1] "=&r"(q1),
|
||||||
[p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3),
|
[p2] "=&r"(p2), [q2] "=&r"(q2), [p3] "=&r"(p3), [q3] "=&r"(q3),
|
||||||
[step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1),
|
[step2] "=&r"(step2), [step1] "=&r"(step1), [temp1] "=&r"(temp1),
|
||||||
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
|
[temp2] "=&r"(temp2), [temp3] "=&r"(temp3), [temp4] "=&r"(temp4),
|
||||||
[pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p),
|
[pTemp0] "=&r"(pTemp0), [pTemp1] "=&r"(pTemp1), [p] "+&r"(p),
|
||||||
[size]"+&r"(size)
|
[size] "+&r"(size)
|
||||||
: [vstride]"r"(vstride), [ithresh]"r"(ithresh),
|
: [vstride] "r"(vstride), [ithresh] "r"(ithresh),
|
||||||
[hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride),
|
[hev_thresh] "r"(hev_thresh), [hstride] "r"(hstride),
|
||||||
[VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
|
[VP8kclip1] "r"(VP8kclip1), [thresh2] "r"(thresh2)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// on macroblock edges
|
// on macroblock edges
|
||||||
static void VFilter16(uint8_t* p, int stride,
|
static void VFilter16(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
|
FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16(uint8_t* p, int stride,
|
static void HFilter16(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
|
FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,8 +449,8 @@ static void HFilter8(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on three inner edges
|
// on three inner edges
|
||||||
static void VFilter16i(uint8_t* p, int stride,
|
static void VFilter16i(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 3; k > 0; --k) {
|
for (k = 3; k > 0; --k) {
|
||||||
p += 4 * stride;
|
p += 4 * stride;
|
||||||
@@ -460,8 +458,8 @@ static void VFilter16i(uint8_t* p, int stride,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16i(uint8_t* p, int stride,
|
static void HFilter16i(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 3; k > 0; --k) {
|
for (k = 3; k > 0; --k) {
|
||||||
p += 4;
|
p += 4;
|
||||||
@@ -489,7 +487,7 @@ static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
|
|||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
||||||
uint8_t* p1 = p - stride;
|
uint8_t* p1 = p - stride;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"li %[i], 16 \n\t"
|
"li %[i], 16 \n\t"
|
||||||
@@ -533,31 +531,32 @@ static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
|
|||||||
"bgtz %[i], 0b \n\t"
|
"bgtz %[i], 0b \n\t"
|
||||||
" addiu %[p], %[p], 1 \n\t"
|
" addiu %[p], %[p], 1 \n\t"
|
||||||
" .set pop \n\t"
|
" .set pop \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [temp8] "=&r"(temp8),
|
||||||
[p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1)
|
[p] "+&r"(p), [i] "=&r"(i), [p1] "+&r"(p1)
|
||||||
: [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
|
: [stride] "r"(stride), [VP8kclip1] "r"(VP8kclip1), [thresh2] "r"(thresh2)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEMP0 = SRC[A + A1 * BPS]
|
// TEMP0 = SRC[A + A1 * BPS]
|
||||||
// TEMP1 = SRC[B + B1 * BPS]
|
// TEMP1 = SRC[B + B1 * BPS]
|
||||||
// TEMP2 = SRC[C + C1 * BPS]
|
// TEMP2 = SRC[C + C1 * BPS]
|
||||||
// TEMP3 = SRC[D + D1 * BPS]
|
// TEMP3 = SRC[D + D1 * BPS]
|
||||||
|
// clang-format off
|
||||||
#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \
|
#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \
|
||||||
A, A1, B, B1, C, C1, D, D1, SRC) \
|
A, A1, B, B1, C, C1, D, D1, SRC) \
|
||||||
"lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
"lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
||||||
"lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
"lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
||||||
"lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
"lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
||||||
"lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
"lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
|
static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
|
||||||
int i;
|
int i;
|
||||||
const int thresh2 = 2 * thresh + 1;
|
const int thresh2 = 2 * thresh + 1;
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
".set push \n\t"
|
".set push \n\t"
|
||||||
".set noreorder \n\t"
|
".set noreorder \n\t"
|
||||||
"li %[i], 16 \n\t"
|
"li %[i], 16 \n\t"
|
||||||
@@ -622,14 +621,16 @@ static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
|
|||||||
|
|
||||||
// DST[A * BPS] = TEMP0
|
// DST[A * BPS] = TEMP0
|
||||||
// DST[B + C * BPS] = TEMP1
|
// DST[B + C * BPS] = TEMP1
|
||||||
|
// clang-format off
|
||||||
#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \
|
#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \
|
||||||
"usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \
|
"usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \
|
||||||
"usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t"
|
"usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void VE4(uint8_t* dst) { // vertical
|
static void VE4(uint8_t* dst) { // vertical
|
||||||
const uint8_t* top = dst - BPS;
|
const uint8_t* top = dst - BPS;
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], -1(%[top]) \n\t"
|
"ulw %[temp0], -1(%[top]) \n\t"
|
||||||
"ulh %[temp1], 3(%[top]) \n\t"
|
"ulh %[temp1], 3(%[top]) \n\t"
|
||||||
"preceu.ph.qbr %[temp2], %[temp0] \n\t"
|
"preceu.ph.qbr %[temp2], %[temp0] \n\t"
|
||||||
@@ -645,20 +646,19 @@ static void VE4(uint8_t* dst) { // vertical
|
|||||||
"addq.ph %[temp6], %[temp6], %[temp3] \n\t"
|
"addq.ph %[temp6], %[temp6], %[temp3] \n\t"
|
||||||
"shra_r.ph %[temp2], %[temp2], 2 \n\t"
|
"shra_r.ph %[temp2], %[temp2], 2 \n\t"
|
||||||
"shra_r.ph %[temp6], %[temp6], 2 \n\t"
|
"shra_r.ph %[temp6], %[temp6], 2 \n\t"
|
||||||
"precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t"
|
"precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" //
|
||||||
STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst)
|
STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst) //
|
||||||
STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst)
|
STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst)
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6)
|
[temp6] "=&r"(temp6)
|
||||||
: [top]"r"(top), [dst]"r"(dst)
|
: [top] "r"(top), [dst] "r"(dst)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DC4(uint8_t* dst) { // DC
|
static void DC4(uint8_t* dst) { // DC
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t"
|
"ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t"
|
||||||
LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
||||||
"ins %[temp1], %[temp2], 8, 8 \n\t"
|
"ins %[temp1], %[temp2], 8, 8 \n\t"
|
||||||
@@ -668,8 +668,8 @@ static void DC4(uint8_t* dst) { // DC
|
|||||||
"raddu.w.qb %[temp1], %[temp1] \n\t"
|
"raddu.w.qb %[temp1], %[temp1] \n\t"
|
||||||
"addu %[temp0], %[temp0], %[temp1] \n\t"
|
"addu %[temp0], %[temp0], %[temp1] \n\t"
|
||||||
"shra_r.w %[temp0], %[temp0], 3 \n\t"
|
"shra_r.w %[temp0], %[temp0], 3 \n\t"
|
||||||
"replv.qb %[temp0], %[temp0] \n\t"
|
"replv.qb %[temp0], %[temp0] \n\t" //
|
||||||
STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst)
|
STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst) //
|
||||||
STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst)
|
STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst)
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4)
|
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4)
|
||||||
@@ -681,9 +681,9 @@ static void DC4(uint8_t* dst) { // DC
|
|||||||
static void RD4(uint8_t* dst) { // Down-right
|
static void RD4(uint8_t* dst) { // Down-right
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8;
|
int temp5, temp6, temp7, temp8;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
||||||
"ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t"
|
"ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t" //
|
||||||
"ins %[temp1], %[temp0], 16, 16 \n\t"
|
"ins %[temp1], %[temp0], 16, 16 \n\t"
|
||||||
"preceu.ph.qbr %[temp5], %[temp7] \n\t"
|
"preceu.ph.qbr %[temp5], %[temp7] \n\t"
|
||||||
"ins %[temp2], %[temp1], 16, 16 \n\t"
|
"ins %[temp2], %[temp1], 16, 16 \n\t"
|
||||||
@@ -702,17 +702,17 @@ static void RD4(uint8_t* dst) { // Down-right
|
|||||||
"shll.ph %[temp0], %[temp0], 1 \n\t"
|
"shll.ph %[temp0], %[temp0], 1 \n\t"
|
||||||
"shra_r.ph %[temp1], %[temp1], 2 \n\t"
|
"shra_r.ph %[temp1], %[temp1], 2 \n\t"
|
||||||
"addq.ph %[temp8], %[temp0], %[temp8] \n\t"
|
"addq.ph %[temp8], %[temp0], %[temp8] \n\t"
|
||||||
"lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t"
|
"lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t" //
|
||||||
"precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t"
|
"precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t"
|
||||||
"shra_r.ph %[temp8], %[temp8], 2 \n\t"
|
"shra_r.ph %[temp8], %[temp8], 2 \n\t"
|
||||||
"ins %[temp7], %[temp5], 0, 8 \n\t"
|
"ins %[temp7], %[temp5], 0, 8 \n\t"
|
||||||
"precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t"
|
"precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t"
|
||||||
"raddu.w.qb %[temp4], %[temp7] \n\t"
|
"raddu.w.qb %[temp4], %[temp7] \n\t"
|
||||||
"precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t"
|
"precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t"
|
||||||
"shra_r.w %[temp4], %[temp4], 2 \n\t"
|
"shra_r.w %[temp4], %[temp4], 2 \n\t" //
|
||||||
STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst)
|
STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst)
|
||||||
"prepend %[temp2], %[temp8], 8 \n\t"
|
"prepend %[temp2], %[temp8], 8 \n\t"
|
||||||
"prepend %[temp6], %[temp4], 8 \n\t"
|
"prepend %[temp6], %[temp4], 8 \n\t" //
|
||||||
STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst)
|
STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst)
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
||||||
@@ -724,14 +724,16 @@ static void RD4(uint8_t* dst) { // Down-right
|
|||||||
|
|
||||||
// TEMP0 = SRC[A * BPS]
|
// TEMP0 = SRC[A * BPS]
|
||||||
// TEMP1 = SRC[B + C * BPS]
|
// TEMP1 = SRC[B + C * BPS]
|
||||||
|
// clang-format off
|
||||||
#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \
|
#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \
|
||||||
"ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
"ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
|
||||||
"ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t"
|
"ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void LD4(uint8_t* dst) { // Down-Left
|
static void LD4(uint8_t* dst) { // Down-Left
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8, temp9;
|
int temp5, temp6, temp7, temp8, temp9;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
|
LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
|
||||||
"preceu.ph.qbl %[temp2], %[temp0] \n\t"
|
"preceu.ph.qbl %[temp2], %[temp0] \n\t"
|
||||||
"preceu.ph.qbr %[temp3], %[temp0] \n\t"
|
"preceu.ph.qbr %[temp3], %[temp0] \n\t"
|
||||||
@@ -778,7 +780,7 @@ static void LD4(uint8_t* dst) { // Down-Left
|
|||||||
static void DC8uv(uint8_t* dst) { // DC
|
static void DC8uv(uint8_t* dst) { // DC
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8, temp9;
|
int temp5, temp6, temp7, temp8, temp9;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
|
LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
|
||||||
LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
||||||
LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst)
|
LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst)
|
||||||
@@ -814,7 +816,7 @@ static void DC8uv(uint8_t* dst) { // DC
|
|||||||
|
|
||||||
static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
|
static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
|
||||||
int temp0, temp1;
|
int temp0, temp1;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
|
LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
|
||||||
"raddu.w.qb %[temp0], %[temp0] \n\t"
|
"raddu.w.qb %[temp0], %[temp0] \n\t"
|
||||||
"raddu.w.qb %[temp1], %[temp1] \n\t"
|
"raddu.w.qb %[temp1], %[temp1] \n\t"
|
||||||
@@ -838,7 +840,7 @@ static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
|
|||||||
static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
|
static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8;
|
int temp5, temp6, temp7, temp8;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
|
||||||
LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst)
|
LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst)
|
||||||
"addu %[temp2], %[temp2], %[temp3] \n\t"
|
"addu %[temp2], %[temp2], %[temp3] \n\t"
|
||||||
@@ -870,6 +872,7 @@ static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
|
|||||||
#undef STORE_8_BYTES
|
#undef STORE_8_BYTES
|
||||||
#undef LOAD_4_BYTES
|
#undef LOAD_4_BYTES
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define CLIPPING(SIZE) \
|
#define CLIPPING(SIZE) \
|
||||||
"preceu.ph.qbl %[temp2], %[temp0] \n\t" \
|
"preceu.ph.qbl %[temp2], %[temp0] \n\t" \
|
||||||
"preceu.ph.qbr %[temp0], %[temp0] \n\t" \
|
"preceu.ph.qbr %[temp0], %[temp0] \n\t" \
|
||||||
@@ -894,11 +897,11 @@ static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
|
|||||||
"precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \
|
"precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \
|
||||||
".endif \n\t"
|
".endif \n\t"
|
||||||
|
|
||||||
|
#define CLIP_8B_TO_DST(DST, TOP, SIZE) \
|
||||||
#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \
|
do { \
|
||||||
int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \
|
int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \
|
||||||
int temp0, temp1, temp2, temp3; \
|
int temp0, temp1, temp2, temp3; \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile( \
|
||||||
".if " #SIZE " < 8 \n\t" \
|
".if " #SIZE " < 8 \n\t" \
|
||||||
"ulw %[temp0], 0(%[top]) \n\t" \
|
"ulw %[temp0], 0(%[top]) \n\t" \
|
||||||
"subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \
|
"subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \
|
||||||
@@ -924,9 +927,11 @@ static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
|
|||||||
: [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \
|
: [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \
|
||||||
: "memory" \
|
: "memory" \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#define CLIP_TO_DST(DST, SIZE) do { \
|
#define CLIP_TO_DST(DST, SIZE) \
|
||||||
|
do { \
|
||||||
int y; \
|
int y; \
|
||||||
const uint8_t* top = (DST) - BPS; \
|
const uint8_t* top = (DST) - BPS; \
|
||||||
const int top_1 = ((int)top[-1] << 16) + top[-1]; \
|
const int top_1 = ((int)top[-1] << 16) + top[-1]; \
|
||||||
@@ -934,12 +939,10 @@ static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
|
|||||||
CLIP_8B_TO_DST((DST), top, (SIZE)); \
|
CLIP_8B_TO_DST((DST), top, (SIZE)); \
|
||||||
(DST) += BPS; \
|
(DST) += BPS; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define TRUE_MOTION(DST, SIZE) \
|
#define TRUE_MOTION(DST, SIZE) \
|
||||||
static void TrueMotion##SIZE(uint8_t* (DST)) { \
|
static void TrueMotion##SIZE(uint8_t*(DST)) { CLIP_TO_DST((DST), (SIZE)); }
|
||||||
CLIP_TO_DST((DST), (SIZE)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
TRUE_MOTION(dst, 4)
|
TRUE_MOTION(dst, 4)
|
||||||
TRUE_MOTION(dst, 8)
|
TRUE_MOTION(dst, 8)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
//
|
//
|
||||||
// Author(s): Prashant Patil (prashant.patil@imgtec.com)
|
// Author(s): Prashant Patil (prashant.patil@imgtec.com)
|
||||||
|
|
||||||
|
|
||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
|
|
||||||
#if defined(WEBP_USE_MSA)
|
#if defined(WEBP_USE_MSA)
|
||||||
@@ -21,7 +20,8 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Transforms
|
// Transforms
|
||||||
|
|
||||||
#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) { \
|
#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) \
|
||||||
|
{ \
|
||||||
v4i32 a1_m, b1_m, c1_m, d1_m; \
|
v4i32 a1_m, b1_m, c1_m, d1_m; \
|
||||||
v4i32 c_tmp1_m, c_tmp2_m, d_tmp1_m, d_tmp2_m; \
|
v4i32 c_tmp1_m, c_tmp2_m, d_tmp1_m, d_tmp2_m; \
|
||||||
const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \
|
const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \
|
||||||
@@ -36,14 +36,14 @@
|
|||||||
d_tmp2_m = (in3 * sinpi8sqrt2) >> 16; \
|
d_tmp2_m = (in3 * sinpi8sqrt2) >> 16; \
|
||||||
d1_m = d_tmp1_m + d_tmp2_m; \
|
d1_m = d_tmp1_m + d_tmp2_m; \
|
||||||
BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
|
BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TransformOne(const int16_t* WEBP_RESTRICT in,
|
static void TransformOne(const int16_t* WEBP_RESTRICT in,
|
||||||
uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
v8i16 input0, input1;
|
v8i16 input0, input1;
|
||||||
v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
|
v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
|
||||||
v4i32 res0, res1, res2, res3;
|
v4i32 res0, res1, res2, res3;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
v16i8 dest0, dest1, dest2, dest3;
|
v16i8 dest0, dest1, dest2, dest3;
|
||||||
|
|
||||||
LD_SH2(in, 8, input0, input1);
|
LD_SH2(in, 8, input0, input1);
|
||||||
@@ -55,10 +55,10 @@ static void TransformOne(const int16_t* WEBP_RESTRICT in,
|
|||||||
SRARI_W4_SW(vt0, vt1, vt2, vt3, 3);
|
SRARI_W4_SW(vt0, vt1, vt2, vt3, 3);
|
||||||
TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3);
|
TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3);
|
||||||
LD_SB4(dst, BPS, dest0, dest1, dest2, dest3);
|
LD_SB4(dst, BPS, dest0, dest1, dest2, dest3);
|
||||||
ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3,
|
ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, res0, res1,
|
||||||
res0, res1, res2, res3);
|
res2, res3);
|
||||||
ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3,
|
ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, res0, res1, res2,
|
||||||
res0, res1, res2, res3);
|
res3);
|
||||||
ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3);
|
ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3);
|
||||||
CLIP_SW4_0_255(res0, res1, res2, res3);
|
CLIP_SW4_0_255(res0, res1, res2, res3);
|
||||||
PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1);
|
PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1);
|
||||||
@@ -77,10 +77,10 @@ static void TransformTwo(const int16_t* WEBP_RESTRICT in,
|
|||||||
static void TransformWHT(const int16_t* WEBP_RESTRICT in,
|
static void TransformWHT(const int16_t* WEBP_RESTRICT in,
|
||||||
int16_t* WEBP_RESTRICT out) {
|
int16_t* WEBP_RESTRICT out) {
|
||||||
v8i16 input0, input1;
|
v8i16 input0, input1;
|
||||||
const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
|
const v8i16 mask0 = {0, 1, 2, 3, 8, 9, 10, 11};
|
||||||
const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
|
const v8i16 mask1 = {4, 5, 6, 7, 12, 13, 14, 15};
|
||||||
const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 };
|
const v8i16 mask2 = {0, 4, 8, 12, 1, 5, 9, 13};
|
||||||
const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 };
|
const v8i16 mask3 = {3, 7, 11, 15, 2, 6, 10, 14};
|
||||||
v8i16 tmp0, tmp1, tmp2, tmp3;
|
v8i16 tmp0, tmp1, tmp2, tmp3;
|
||||||
v8i16 out0, out1;
|
v8i16 out0, out1;
|
||||||
|
|
||||||
@@ -131,24 +131,23 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]);
|
const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]);
|
||||||
const int in2 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
|
const int in2 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
|
||||||
const int in3 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
|
const int in3 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
|
||||||
v4i32 tmp0 = { 0 };
|
v4i32 tmp0 = {0};
|
||||||
v4i32 out0 = __msa_fill_w(a + d4);
|
v4i32 out0 = __msa_fill_w(a + d4);
|
||||||
v4i32 out1 = __msa_fill_w(a + c4);
|
v4i32 out1 = __msa_fill_w(a + c4);
|
||||||
v4i32 out2 = __msa_fill_w(a - c4);
|
v4i32 out2 = __msa_fill_w(a - c4);
|
||||||
v4i32 out3 = __msa_fill_w(a - d4);
|
v4i32 out3 = __msa_fill_w(a - d4);
|
||||||
v4i32 res0, res1, res2, res3;
|
v4i32 res0, res1, res2, res3;
|
||||||
const v4i32 zero = { 0 };
|
const v4i32 zero = {0};
|
||||||
v16u8 dest0, dest1, dest2, dest3;
|
v16u8 dest0, dest1, dest2, dest3;
|
||||||
|
|
||||||
INSERT_W4_SW(in3, in2, -in2, -in3, tmp0);
|
INSERT_W4_SW(in3, in2, -in2, -in3, tmp0);
|
||||||
ADD4(out0, tmp0, out1, tmp0, out2, tmp0, out3, tmp0,
|
ADD4(out0, tmp0, out1, tmp0, out2, tmp0, out3, tmp0, out0, out1, out2, out3);
|
||||||
out0, out1, out2, out3);
|
|
||||||
SRAI_W4_SW(out0, out1, out2, out3, 3);
|
SRAI_W4_SW(out0, out1, out2, out3, 3);
|
||||||
LD_UB4(dst, BPS, dest0, dest1, dest2, dest3);
|
LD_UB4(dst, BPS, dest0, dest1, dest2, dest3);
|
||||||
ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3,
|
ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, res0, res1,
|
||||||
res0, res1, res2, res3);
|
res2, res3);
|
||||||
ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3,
|
ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, res0, res1, res2,
|
||||||
res0, res1, res2, res3);
|
res3);
|
||||||
ADD4(res0, out0, res1, out1, res2, out2, res3, out3, res0, res1, res2, res3);
|
ADD4(res0, out0, res1, out1, res2, out2, res3, out3, res0, res1, res2, res3);
|
||||||
CLIP_SW4_0_255(res0, res1, res2, res3);
|
CLIP_SW4_0_255(res0, res1, res2, res3);
|
||||||
PCKEV_B2_SW(res0, res1, res2, res3, out0, out1);
|
PCKEV_B2_SW(res0, res1, res2, res3, out0, out1);
|
||||||
@@ -159,26 +158,30 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Edge filtering functions
|
// Edge filtering functions
|
||||||
|
|
||||||
#define FLIP_SIGN2(in0, in1, out0, out1) { \
|
#define FLIP_SIGN2(in0, in1, out0, out1) \
|
||||||
|
{ \
|
||||||
out0 = (v16i8)__msa_xori_b(in0, 0x80); \
|
out0 = (v16i8)__msa_xori_b(in0, 0x80); \
|
||||||
out1 = (v16i8)__msa_xori_b(in1, 0x80); \
|
out1 = (v16i8)__msa_xori_b(in1, 0x80); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLIP_SIGN4(in0, in1, in2, in3, out0, out1, out2, out3) { \
|
#define FLIP_SIGN4(in0, in1, in2, in3, out0, out1, out2, out3) \
|
||||||
|
{ \
|
||||||
FLIP_SIGN2(in0, in1, out0, out1); \
|
FLIP_SIGN2(in0, in1, out0, out1); \
|
||||||
FLIP_SIGN2(in2, in3, out2, out3); \
|
FLIP_SIGN2(in2, in3, out2, out3); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FILT_VAL(q0_m, p0_m, mask, filt) do { \
|
#define FILT_VAL(q0_m, p0_m, mask, filt) \
|
||||||
|
do { \
|
||||||
v16i8 q0_sub_p0; \
|
v16i8 q0_sub_p0; \
|
||||||
q0_sub_p0 = __msa_subs_s_b(q0_m, p0_m); \
|
q0_sub_p0 = __msa_subs_s_b(q0_m, p0_m); \
|
||||||
filt = __msa_adds_s_b(filt, q0_sub_p0); \
|
filt = __msa_adds_s_b(filt, q0_sub_p0); \
|
||||||
filt = __msa_adds_s_b(filt, q0_sub_p0); \
|
filt = __msa_adds_s_b(filt, q0_sub_p0); \
|
||||||
filt = __msa_adds_s_b(filt, q0_sub_p0); \
|
filt = __msa_adds_s_b(filt, q0_sub_p0); \
|
||||||
filt = filt & mask; \
|
filt = filt & mask; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define FILT2(q_m, p_m, q, p) do { \
|
#define FILT2(q_m, p_m, q, p) \
|
||||||
|
do { \
|
||||||
u_r = SRAI_H(temp1, 7); \
|
u_r = SRAI_H(temp1, 7); \
|
||||||
u_r = __msa_sat_s_h(u_r, 7); \
|
u_r = __msa_sat_s_h(u_r, 7); \
|
||||||
u_l = SRAI_H(temp3, 7); \
|
u_l = SRAI_H(temp3, 7); \
|
||||||
@@ -188,9 +191,10 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
p_m = __msa_adds_s_b(p_m, u); \
|
p_m = __msa_adds_s_b(p_m, u); \
|
||||||
q = __msa_xori_b((v16u8)q_m, 0x80); \
|
q = __msa_xori_b((v16u8)q_m, 0x80); \
|
||||||
p = __msa_xori_b((v16u8)p_m, 0x80); \
|
p = __msa_xori_b((v16u8)p_m, 0x80); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev) do { \
|
#define LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev) \
|
||||||
|
do { \
|
||||||
v16i8 p1_m, p0_m, q0_m, q1_m; \
|
v16i8 p1_m, p0_m, q0_m, q1_m; \
|
||||||
v16i8 filt, t1, t2; \
|
v16i8 filt, t1, t2; \
|
||||||
const v16i8 cnst4b = __msa_ldi_b(4); \
|
const v16i8 cnst4b = __msa_ldi_b(4); \
|
||||||
@@ -215,9 +219,10 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
q1 = __msa_xori_b((v16u8)q1_m, 0x80); \
|
q1 = __msa_xori_b((v16u8)q1_m, 0x80); \
|
||||||
p1_m = __msa_adds_s_b(p1_m, filt); \
|
p1_m = __msa_adds_s_b(p1_m, filt); \
|
||||||
p1 = __msa_xori_b((v16u8)p1_m, 0x80); \
|
p1 = __msa_xori_b((v16u8)p1_m, 0x80); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) do { \
|
#define LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) \
|
||||||
|
do { \
|
||||||
v16i8 p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \
|
v16i8 p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \
|
||||||
v16i8 u, filt, t1, t2, filt_sign; \
|
v16i8 u, filt, t1, t2, filt_sign; \
|
||||||
v8i16 filt_r, filt_l, u_r, u_l; \
|
v8i16 filt_r, filt_l, u_r, u_l; \
|
||||||
@@ -257,12 +262,11 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
temp1 = temp1 + temp0; \
|
temp1 = temp1 + temp0; \
|
||||||
temp3 = temp3 + temp2; \
|
temp3 = temp3 + temp2; \
|
||||||
FILT2(q0_m, p0_m, q0, p0); \
|
FILT2(q0_m, p0_m, q0, p0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LPF_MASK_HEV(p3_in, p2_in, p1_in, p0_in, \
|
#define LPF_MASK_HEV(p3_in, p2_in, p1_in, p0_in, q0_in, q1_in, q2_in, q3_in, \
|
||||||
q0_in, q1_in, q2_in, q3_in, \
|
limit_in, b_limit_in, thresh_in, hev_out, mask_out) \
|
||||||
limit_in, b_limit_in, thresh_in, \
|
do { \
|
||||||
hev_out, mask_out) do { \
|
|
||||||
v16u8 p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \
|
v16u8 p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \
|
||||||
v16u8 p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \
|
v16u8 p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \
|
||||||
v16u8 flat_out; \
|
v16u8 flat_out; \
|
||||||
@@ -291,16 +295,18 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
mask_out = __msa_max_u_b(q2_asub_q1_m, mask_out); \
|
mask_out = __msa_max_u_b(q2_asub_q1_m, mask_out); \
|
||||||
mask_out = (limit_in < mask_out); \
|
mask_out = (limit_in < mask_out); \
|
||||||
mask_out = __msa_xori_b(mask_out, 0xff); \
|
mask_out = __msa_xori_b(mask_out, 0xff); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) do { \
|
#define ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) \
|
||||||
|
do { \
|
||||||
const uint16_t tmp0_h = __msa_copy_s_h((v8i16)in1, in1_idx); \
|
const uint16_t tmp0_h = __msa_copy_s_h((v8i16)in1, in1_idx); \
|
||||||
const uint32_t tmp0_w = __msa_copy_s_w((v4i32)in0, in0_idx); \
|
const uint32_t tmp0_w = __msa_copy_s_w((v4i32)in0, in0_idx); \
|
||||||
SW(tmp0_w, pdst); \
|
SW(tmp0_w, pdst); \
|
||||||
SH(tmp0_h, pdst + stride); \
|
SH(tmp0_h, pdst + stride); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ST6x4_UB(in0, start_in0_idx, in1, start_in1_idx, pdst, stride) do { \
|
#define ST6x4_UB(in0, start_in0_idx, in1, start_in1_idx, pdst, stride) \
|
||||||
|
do { \
|
||||||
uint8_t* ptmp1 = (uint8_t*)pdst; \
|
uint8_t* ptmp1 = (uint8_t*)pdst; \
|
||||||
ST6x1_UB(in0, start_in0_idx, in1, start_in1_idx, ptmp1, 4); \
|
ST6x1_UB(in0, start_in0_idx, in1, start_in1_idx, ptmp1, 4); \
|
||||||
ptmp1 += stride; \
|
ptmp1 += stride; \
|
||||||
@@ -309,9 +315,10 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
ST6x1_UB(in0, start_in0_idx + 2, in1, start_in1_idx + 2, ptmp1, 4); \
|
ST6x1_UB(in0, start_in0_idx + 2, in1, start_in1_idx + 2, ptmp1, 4); \
|
||||||
ptmp1 += stride; \
|
ptmp1 += stride; \
|
||||||
ST6x1_UB(in0, start_in0_idx + 3, in1, start_in1_idx + 3, ptmp1, 4); \
|
ST6x1_UB(in0, start_in0_idx + 3, in1, start_in1_idx + 3, ptmp1, 4); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LPF_SIMPLE_FILT(p1_in, p0_in, q0_in, q1_in, mask) do { \
|
#define LPF_SIMPLE_FILT(p1_in, p0_in, q0_in, q1_in, mask) \
|
||||||
|
do { \
|
||||||
v16i8 p1_m, p0_m, q0_m, q1_m, filt, filt1, filt2; \
|
v16i8 p1_m, p0_m, q0_m, q1_m, filt, filt1, filt2; \
|
||||||
const v16i8 cnst4b = __msa_ldi_b(4); \
|
const v16i8 cnst4b = __msa_ldi_b(4); \
|
||||||
const v16i8 cnst3b = __msa_ldi_b(3); \
|
const v16i8 cnst3b = __msa_ldi_b(3); \
|
||||||
@@ -327,9 +334,10 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
p0_m = __msa_adds_s_b(p0_m, filt2); \
|
p0_m = __msa_adds_s_b(p0_m, filt2); \
|
||||||
q0_in = __msa_xori_b((v16u8)q0_m, 0x80); \
|
q0_in = __msa_xori_b((v16u8)q0_m, 0x80); \
|
||||||
p0_in = __msa_xori_b((v16u8)p0_m, 0x80); \
|
p0_in = __msa_xori_b((v16u8)p0_m, 0x80); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask) do { \
|
#define LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask) \
|
||||||
|
do { \
|
||||||
v16u8 p1_a_sub_q1, p0_a_sub_q0; \
|
v16u8 p1_a_sub_q1, p0_a_sub_q0; \
|
||||||
\
|
\
|
||||||
p0_a_sub_q0 = __msa_asub_u_b(p0, q0); \
|
p0_a_sub_q0 = __msa_asub_u_b(p0, q0); \
|
||||||
@@ -338,10 +346,10 @@ static void TransformAC3(const int16_t* WEBP_RESTRICT in,
|
|||||||
p0_a_sub_q0 = __msa_adds_u_b(p0_a_sub_q0, p0_a_sub_q0); \
|
p0_a_sub_q0 = __msa_adds_u_b(p0_a_sub_q0, p0_a_sub_q0); \
|
||||||
mask = __msa_adds_u_b(p0_a_sub_q0, p1_a_sub_q1); \
|
mask = __msa_adds_u_b(p0_a_sub_q0, p1_a_sub_q1); \
|
||||||
mask = (mask <= b_limit); \
|
mask = (mask <= b_limit); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void VFilter16(uint8_t* src, int stride,
|
static void VFilter16(uint8_t* src, int stride, int b_limit_in, int limit_in,
|
||||||
int b_limit_in, int limit_in, int thresh_in) {
|
int thresh_in) {
|
||||||
uint8_t* ptemp = src - 4 * stride;
|
uint8_t* ptemp = src - 4 * stride;
|
||||||
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
||||||
v16u8 mask, hev;
|
v16u8 mask, hev;
|
||||||
@@ -350,8 +358,8 @@ static void VFilter16(uint8_t* src, int stride,
|
|||||||
const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
|
const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
|
||||||
|
|
||||||
LD_UB8(ptemp, stride, p3, p2, p1, p0, q0, q1, q2, q3);
|
LD_UB8(ptemp, stride, p3, p2, p1, p0, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
||||||
ptemp = src - 3 * stride;
|
ptemp = src - 3 * stride;
|
||||||
ST_UB4(p2, p1, p0, q0, ptemp, stride);
|
ST_UB4(p2, p1, p0, q0, ptemp, stride);
|
||||||
@@ -359,8 +367,8 @@ static void VFilter16(uint8_t* src, int stride,
|
|||||||
ST_UB2(q1, q2, ptemp, stride);
|
ST_UB2(q1, q2, ptemp, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16(uint8_t* src, int stride,
|
static void HFilter16(uint8_t* src, int stride, int b_limit_in, int limit_in,
|
||||||
int b_limit_in, int limit_in, int thresh_in) {
|
int thresh_in) {
|
||||||
uint8_t* ptmp = src - 4;
|
uint8_t* ptmp = src - 4;
|
||||||
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
||||||
v16u8 mask, hev;
|
v16u8 mask, hev;
|
||||||
@@ -374,11 +382,11 @@ static void HFilter16(uint8_t* src, int stride,
|
|||||||
LD_UB8(ptmp, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
LD_UB8(ptmp, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
||||||
ptmp += (8 * stride);
|
ptmp += (8 * stride);
|
||||||
LD_UB8(ptmp, stride, row8, row9, row10, row11, row12, row13, row14, row15);
|
LD_UB8(ptmp, stride, row8, row9, row10, row11, row12, row13, row14, row15);
|
||||||
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
|
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, row8,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15,
|
row9, row10, row11, row12, row13, row14, row15, p3, p2,
|
||||||
p3, p2, p1, p0, q0, q1, q2, q3);
|
p1, p0, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
||||||
ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
|
ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
|
||||||
ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4);
|
ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4);
|
||||||
@@ -420,8 +428,8 @@ static void HFilter16(uint8_t* src, int stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on three inner edges
|
// on three inner edges
|
||||||
static void VFilterHorEdge16i(uint8_t* src, int stride,
|
static void VFilterHorEdge16i(uint8_t* src, int stride, int b_limit, int limit,
|
||||||
int b_limit, int limit, int thresh) {
|
int thresh) {
|
||||||
v16u8 mask, hev;
|
v16u8 mask, hev;
|
||||||
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
||||||
const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh);
|
const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh);
|
||||||
@@ -429,21 +437,21 @@ static void VFilterHorEdge16i(uint8_t* src, int stride,
|
|||||||
const v16u8 limit0 = (v16u8)__msa_fill_b(limit);
|
const v16u8 limit0 = (v16u8)__msa_fill_b(limit);
|
||||||
|
|
||||||
LD_UB8((src - 4 * stride), stride, p3, p2, p1, p0, q0, q1, q2, q3);
|
LD_UB8((src - 4 * stride), stride, p3, p2, p1, p0, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
||||||
ST_UB4(p1, p0, q0, q1, (src - 2 * stride), stride);
|
ST_UB4(p1, p0, q0, q1, (src - 2 * stride), stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VFilter16i(uint8_t* src_y, int stride,
|
static void VFilter16i(uint8_t* src_y, int stride, int b_limit, int limit,
|
||||||
int b_limit, int limit, int thresh) {
|
int thresh) {
|
||||||
VFilterHorEdge16i(src_y + 4 * stride, stride, b_limit, limit, thresh);
|
VFilterHorEdge16i(src_y + 4 * stride, stride, b_limit, limit, thresh);
|
||||||
VFilterHorEdge16i(src_y + 8 * stride, stride, b_limit, limit, thresh);
|
VFilterHorEdge16i(src_y + 8 * stride, stride, b_limit, limit, thresh);
|
||||||
VFilterHorEdge16i(src_y + 12 * stride, stride, b_limit, limit, thresh);
|
VFilterHorEdge16i(src_y + 12 * stride, stride, b_limit, limit, thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilterVertEdge16i(uint8_t* src, int stride,
|
static void HFilterVertEdge16i(uint8_t* src, int stride, int b_limit, int limit,
|
||||||
int b_limit, int limit, int thresh) {
|
int thresh) {
|
||||||
v16u8 mask, hev;
|
v16u8 mask, hev;
|
||||||
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
|
||||||
v16u8 row0, row1, row2, row3, row4, row5, row6, row7;
|
v16u8 row0, row1, row2, row3, row4, row5, row6, row7;
|
||||||
@@ -454,13 +462,13 @@ static void HFilterVertEdge16i(uint8_t* src, int stride,
|
|||||||
const v16u8 limit0 = (v16u8)__msa_fill_b(limit);
|
const v16u8 limit0 = (v16u8)__msa_fill_b(limit);
|
||||||
|
|
||||||
LD_UB8(src - 4, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
LD_UB8(src - 4, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
||||||
LD_UB8(src - 4 + (8 * stride), stride,
|
LD_UB8(src - 4 + (8 * stride), stride, row8, row9, row10, row11, row12, row13,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15);
|
row14, row15);
|
||||||
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
|
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, row8,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15,
|
row9, row10, row11, row12, row13, row14, row15, p3, p2,
|
||||||
p3, p2, p1, p0, q0, q1, q2, q3);
|
p1, p0, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
||||||
ILVR_B2_SH(p0, p1, q1, q0, tmp0, tmp1);
|
ILVR_B2_SH(p0, p1, q1, q0, tmp0, tmp1);
|
||||||
ILVRL_H2_SH(tmp1, tmp0, tmp2, tmp3);
|
ILVRL_H2_SH(tmp1, tmp0, tmp2, tmp3);
|
||||||
@@ -472,8 +480,8 @@ static void HFilterVertEdge16i(uint8_t* src, int stride,
|
|||||||
ST4x8_UB(tmp4, tmp5, src, stride);
|
ST4x8_UB(tmp4, tmp5, src, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16i(uint8_t* src_y, int stride,
|
static void HFilter16i(uint8_t* src_y, int stride, int b_limit, int limit,
|
||||||
int b_limit, int limit, int thresh) {
|
int thresh) {
|
||||||
HFilterVertEdge16i(src_y + 4, stride, b_limit, limit, thresh);
|
HFilterVertEdge16i(src_y + 4, stride, b_limit, limit, thresh);
|
||||||
HFilterVertEdge16i(src_y + 8, stride, b_limit, limit, thresh);
|
HFilterVertEdge16i(src_y + 8, stride, b_limit, limit, thresh);
|
||||||
HFilterVertEdge16i(src_y + 12, stride, b_limit, limit, thresh);
|
HFilterVertEdge16i(src_y + 12, stride, b_limit, limit, thresh);
|
||||||
@@ -496,8 +504,8 @@ static void VFilter8(uint8_t* WEBP_RESTRICT src_u, uint8_t* WEBP_RESTRICT src_v,
|
|||||||
LD_UB8(ptmp_src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v);
|
LD_UB8(ptmp_src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v);
|
||||||
ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0);
|
ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0);
|
||||||
ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3);
|
ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
||||||
p2_d = __msa_copy_s_d((v2i64)p2, 0);
|
p2_d = __msa_copy_s_d((v2i64)p2, 0);
|
||||||
p1_d = __msa_copy_s_d((v2i64)p1, 0);
|
p1_d = __msa_copy_s_d((v2i64)p1, 0);
|
||||||
@@ -538,13 +546,13 @@ static void HFilter8(uint8_t* WEBP_RESTRICT src_u, uint8_t* WEBP_RESTRICT src_v,
|
|||||||
const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
|
const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
|
||||||
|
|
||||||
LD_UB8(ptmp_src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
LD_UB8(ptmp_src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
||||||
LD_UB8(ptmp_src_v, stride,
|
LD_UB8(ptmp_src_v, stride, row8, row9, row10, row11, row12, row13, row14,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15);
|
row15);
|
||||||
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
|
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, row8,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15,
|
row9, row10, row11, row12, row13, row14, row15, p3, p2,
|
||||||
p3, p2, p1, p0, q0, q1, q2, q3);
|
p1, p0, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
|
||||||
ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
|
ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
|
||||||
ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4);
|
ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4);
|
||||||
@@ -562,8 +570,8 @@ static void HFilter8(uint8_t* WEBP_RESTRICT src_u, uint8_t* WEBP_RESTRICT src_v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void VFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
static void VFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
||||||
uint8_t* WEBP_RESTRICT src_v, int stride,
|
uint8_t* WEBP_RESTRICT src_v, int stride, int b_limit_in,
|
||||||
int b_limit_in, int limit_in, int thresh_in) {
|
int limit_in, int thresh_in) {
|
||||||
uint64_t p1_d, p0_d, q0_d, q1_d;
|
uint64_t p1_d, p0_d, q0_d, q1_d;
|
||||||
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
|
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
|
||||||
v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u;
|
v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u;
|
||||||
@@ -578,8 +586,8 @@ static void VFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
|||||||
src_v += (5 * stride);
|
src_v += (5 * stride);
|
||||||
ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0);
|
ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0);
|
||||||
ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3);
|
ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3);
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev,
|
||||||
hev, mask);
|
mask);
|
||||||
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
||||||
p1_d = __msa_copy_s_d((v2i64)p1, 0);
|
p1_d = __msa_copy_s_d((v2i64)p1, 0);
|
||||||
p0_d = __msa_copy_s_d((v2i64)p0, 0);
|
p0_d = __msa_copy_s_d((v2i64)p0, 0);
|
||||||
@@ -594,8 +602,8 @@ static void VFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
static void HFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
||||||
uint8_t* WEBP_RESTRICT src_v, int stride,
|
uint8_t* WEBP_RESTRICT src_v, int stride, int b_limit_in,
|
||||||
int b_limit_in, int limit_in, int thresh_in) {
|
int limit_in, int thresh_in) {
|
||||||
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
|
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
|
||||||
v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8;
|
v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8;
|
||||||
v16u8 row9, row10, row11, row12, row13, row14, row15;
|
v16u8 row9, row10, row11, row12, row13, row14, row15;
|
||||||
@@ -605,13 +613,12 @@ static void HFilter8i(uint8_t* WEBP_RESTRICT src_u,
|
|||||||
const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
|
const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
|
||||||
|
|
||||||
LD_UB8(src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
LD_UB8(src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
||||||
LD_UB8(src_v, stride,
|
LD_UB8(src_v, stride, row8, row9, row10, row11, row12, row13, row14, row15);
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15);
|
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, row8,
|
||||||
TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
|
row9, row10, row11, row12, row13, row14, row15, p3, p2,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15,
|
p1, p0, q0, q1, q2, q3);
|
||||||
p3, p2, p1, p0, q0, q1, q2, q3);
|
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev,
|
||||||
LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
|
mask);
|
||||||
hev, mask);
|
|
||||||
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
|
||||||
ILVR_B2_SW(p0, p1, q1, q0, tmp0, tmp1);
|
ILVR_B2_SW(p0, p1, q1, q0, tmp0, tmp1);
|
||||||
ILVRL_H2_SW(tmp1, tmp0, tmp2, tmp3);
|
ILVRL_H2_SW(tmp1, tmp0, tmp2, tmp3);
|
||||||
@@ -645,11 +652,11 @@ static void SimpleHFilter16(uint8_t* src, int stride, int b_limit_in) {
|
|||||||
uint8_t* ptemp_src = src - 2;
|
uint8_t* ptemp_src = src - 2;
|
||||||
|
|
||||||
LD_UB8(ptemp_src, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
LD_UB8(ptemp_src, stride, row0, row1, row2, row3, row4, row5, row6, row7);
|
||||||
LD_UB8(ptemp_src + 8 * stride, stride,
|
LD_UB8(ptemp_src + 8 * stride, stride, row8, row9, row10, row11, row12, row13,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15);
|
row14, row15);
|
||||||
TRANSPOSE16x4_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
|
TRANSPOSE16x4_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, row8,
|
||||||
row8, row9, row10, row11, row12, row13, row14, row15,
|
row9, row10, row11, row12, row13, row14, row15, p1, p0,
|
||||||
p1, p0, q0, q1);
|
q0, q1);
|
||||||
LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask);
|
LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask);
|
||||||
LPF_SIMPLE_FILT(p1, p0, q0, q1, mask);
|
LPF_SIMPLE_FILT(p1, p0, q0, q1, mask);
|
||||||
ILVRL_B2_SH(q0, p0, tmp1, tmp0);
|
ILVRL_B2_SH(q0, p0, tmp1, tmp0);
|
||||||
@@ -694,7 +701,7 @@ static void DC4(uint8_t* dst) { // DC
|
|||||||
static void TM4(uint8_t* dst) {
|
static void TM4(uint8_t* dst) {
|
||||||
const uint8_t* const ptemp = dst - BPS - 1;
|
const uint8_t* const ptemp = dst - BPS - 1;
|
||||||
v8i16 T, d, r0, r1, r2, r3;
|
v8i16 T, d, r0, r1, r2, r3;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 TL = (v8i16)__msa_fill_h(ptemp[0 * BPS]);
|
const v8i16 TL = (v8i16)__msa_fill_h(ptemp[0 * BPS]);
|
||||||
const v8i16 L0 = (v8i16)__msa_fill_h(ptemp[1 * BPS]);
|
const v8i16 L0 = (v8i16)__msa_fill_h(ptemp[1 * BPS]);
|
||||||
const v8i16 L1 = (v8i16)__msa_fill_h(ptemp[2 * BPS]);
|
const v8i16 L1 = (v8i16)__msa_fill_h(ptemp[2 * BPS]);
|
||||||
@@ -714,7 +721,7 @@ static void VE4(uint8_t* dst) { // vertical
|
|||||||
const uint32_t val0 = LW(ptop + 0);
|
const uint32_t val0 = LW(ptop + 0);
|
||||||
const uint32_t val1 = LW(ptop + 4);
|
const uint32_t val1 = LW(ptop + 4);
|
||||||
uint32_t out;
|
uint32_t out;
|
||||||
v16u8 A = { 0 }, B, C, AC, B2, R;
|
v16u8 A = {0}, B, C, AC, B2, R;
|
||||||
|
|
||||||
INSERT_W2_UB(val0, val1, A);
|
INSERT_W2_UB(val0, val1, A);
|
||||||
B = SLDI_UB(A, A, 1);
|
B = SLDI_UB(A, A, 1);
|
||||||
@@ -731,7 +738,7 @@ static void RD4(uint8_t* dst) { // Down-right
|
|||||||
uint32_t val0 = LW(ptop + 0);
|
uint32_t val0 = LW(ptop + 0);
|
||||||
uint32_t val1 = LW(ptop + 4);
|
uint32_t val1 = LW(ptop + 4);
|
||||||
uint32_t val2, val3;
|
uint32_t val2, val3;
|
||||||
v16u8 A, B, C, AC, B2, R, A1 = { 0 };
|
v16u8 A, B, C, AC, B2, R, A1 = {0};
|
||||||
|
|
||||||
INSERT_W2_UB(val0, val1, A1);
|
INSERT_W2_UB(val0, val1, A1);
|
||||||
A = SLDI_UB(A1, A1, 12);
|
A = SLDI_UB(A1, A1, 12);
|
||||||
@@ -759,7 +766,7 @@ static void LD4(uint8_t* dst) { // Down-Left
|
|||||||
uint32_t val0 = LW(ptop + 0);
|
uint32_t val0 = LW(ptop + 0);
|
||||||
uint32_t val1 = LW(ptop + 4);
|
uint32_t val1 = LW(ptop + 4);
|
||||||
uint32_t val2, val3;
|
uint32_t val2, val3;
|
||||||
v16u8 A = { 0 }, B, C, AC, B2, R;
|
v16u8 A = {0}, B, C, AC, B2, R;
|
||||||
|
|
||||||
INSERT_W2_UB(val0, val1, A);
|
INSERT_W2_UB(val0, val1, A);
|
||||||
B = SLDI_UB(A, A, 1);
|
B = SLDI_UB(A, A, 1);
|
||||||
@@ -799,7 +806,7 @@ static void DC16(uint8_t* dst) { // DC
|
|||||||
static void TM16(uint8_t* dst) {
|
static void TM16(uint8_t* dst) {
|
||||||
int j;
|
int j;
|
||||||
v8i16 d1, d2;
|
v8i16 d1, d2;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]);
|
const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]);
|
||||||
const v16i8 T = LD_SB(dst - BPS);
|
const v16i8 T = LD_SB(dst - BPS);
|
||||||
|
|
||||||
@@ -873,10 +880,11 @@ static void DC16NoTopLeft(uint8_t* dst) { // DC with nothing
|
|||||||
|
|
||||||
// Chroma
|
// Chroma
|
||||||
|
|
||||||
#define STORE8x8(out, dst) do { \
|
#define STORE8x8(out, dst) \
|
||||||
|
do { \
|
||||||
SD4(out, out, out, out, dst + 0 * BPS, BPS); \
|
SD4(out, out, out, out, dst + 0 * BPS, BPS); \
|
||||||
SD4(out, out, out, out, dst + 4 * BPS, BPS); \
|
SD4(out, out, out, out, dst + 4 * BPS, BPS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void DC8uv(uint8_t* dst) { // DC
|
static void DC8uv(uint8_t* dst) { // DC
|
||||||
uint32_t dc = 8;
|
uint32_t dc = 8;
|
||||||
@@ -900,7 +908,7 @@ static void DC8uv(uint8_t* dst) { // DC
|
|||||||
static void TM8uv(uint8_t* dst) {
|
static void TM8uv(uint8_t* dst) {
|
||||||
int j;
|
int j;
|
||||||
const v16i8 T1 = LD_SB(dst - BPS);
|
const v16i8 T1 = LD_SB(dst - BPS);
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 T = (v8i16)__msa_ilvr_b(zero, T1);
|
const v8i16 T = (v8i16)__msa_ilvr_b(zero, T1);
|
||||||
const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]);
|
const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]);
|
||||||
const v8i16 d = T - TL;
|
const v8i16 d = T - TL;
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
#if defined(WEBP_USE_NEON)
|
#if defined(WEBP_USE_NEON)
|
||||||
|
|
||||||
#include "src/dsp/neon.h"
|
|
||||||
#include "src/dec/vp8i_dec.h"
|
#include "src/dec/vp8i_dec.h"
|
||||||
|
#include "src/dsp/neon.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// NxM Loading functions
|
// NxM Loading functions
|
||||||
@@ -60,10 +60,11 @@ static WEBP_INLINE void Load4x16_NEON(const uint8_t* const src, int stride,
|
|||||||
|
|
||||||
#else // WORK_AROUND_GCC
|
#else // WORK_AROUND_GCC
|
||||||
|
|
||||||
#define LOADQ_LANE_32b(VALUE, LANE) do { \
|
#define LOADQ_LANE_32b(VALUE, LANE) \
|
||||||
|
do { \
|
||||||
(VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \
|
(VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \
|
||||||
src += stride; \
|
src += stride; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static WEBP_INLINE void Load4x16_NEON(const uint8_t* src, int stride,
|
static WEBP_INLINE void Load4x16_NEON(const uint8_t* src, int stride,
|
||||||
uint8x16_t* const p1,
|
uint8x16_t* const p1,
|
||||||
@@ -111,10 +112,10 @@ static WEBP_INLINE void Load4x16_NEON(const uint8_t* src, int stride,
|
|||||||
#endif // !WORK_AROUND_GCC
|
#endif // !WORK_AROUND_GCC
|
||||||
|
|
||||||
static WEBP_INLINE void Load8x16_NEON(
|
static WEBP_INLINE void Load8x16_NEON(
|
||||||
const uint8_t* const src, int stride,
|
const uint8_t* const src, int stride, uint8x16_t* const p3,
|
||||||
uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1,
|
uint8x16_t* const p2, uint8x16_t* const p1, uint8x16_t* const p0,
|
||||||
uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1,
|
uint8x16_t* const q0, uint8x16_t* const q1, uint8x16_t* const q2,
|
||||||
uint8x16_t* const q2, uint8x16_t* const q3) {
|
uint8x16_t* const q3) {
|
||||||
Load4x16_NEON(src - 2, stride, p3, p2, p1, p0);
|
Load4x16_NEON(src - 2, stride, p3, p2, p1, p0);
|
||||||
Load4x16_NEON(src + 2, stride, q0, q1, q2, q3);
|
Load4x16_NEON(src + 2, stride, q0, q1, q2, q3);
|
||||||
}
|
}
|
||||||
@@ -131,10 +132,10 @@ static WEBP_INLINE void Load16x4_NEON(const uint8_t* const src, int stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void Load16x8_NEON(
|
static WEBP_INLINE void Load16x8_NEON(
|
||||||
const uint8_t* const src, int stride,
|
const uint8_t* const src, int stride, uint8x16_t* const p3,
|
||||||
uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1,
|
uint8x16_t* const p2, uint8x16_t* const p1, uint8x16_t* const p0,
|
||||||
uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1,
|
uint8x16_t* const q0, uint8x16_t* const q1, uint8x16_t* const q2,
|
||||||
uint8x16_t* const q2, uint8x16_t* const q3) {
|
uint8x16_t* const q3) {
|
||||||
Load16x4_NEON(src - 2 * stride, stride, p3, p2, p1, p0);
|
Load16x4_NEON(src - 2 * stride, stride, p3, p2, p1, p0);
|
||||||
Load16x4_NEON(src + 2 * stride, stride, q0, q1, q2, q3);
|
Load16x4_NEON(src + 2 * stride, stride, q0, q1, q2, q3);
|
||||||
}
|
}
|
||||||
@@ -220,8 +221,8 @@ static WEBP_INLINE void Load8x8x2T_NEON(
|
|||||||
|
|
||||||
#endif // !WORK_AROUND_GCC
|
#endif // !WORK_AROUND_GCC
|
||||||
|
|
||||||
static WEBP_INLINE void Store2x8_NEON(const uint8x8x2_t v,
|
static WEBP_INLINE void Store2x8_NEON(const uint8x8x2_t v, uint8_t* const dst,
|
||||||
uint8_t* const dst, int stride) {
|
int stride) {
|
||||||
vst2_lane_u8(dst + 0 * stride, v, 0);
|
vst2_lane_u8(dst + 0 * stride, v, 0);
|
||||||
vst2_lane_u8(dst + 1 * stride, v, 1);
|
vst2_lane_u8(dst + 1 * stride, v, 1);
|
||||||
vst2_lane_u8(dst + 2 * stride, v, 2);
|
vst2_lane_u8(dst + 2 * stride, v, 2);
|
||||||
@@ -244,8 +245,8 @@ static WEBP_INLINE void Store2x16_NEON(const uint8x16_t p0, const uint8x16_t q0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(WORK_AROUND_GCC)
|
#if !defined(WORK_AROUND_GCC)
|
||||||
static WEBP_INLINE void Store4x8_NEON(const uint8x8x4_t v,
|
static WEBP_INLINE void Store4x8_NEON(const uint8x8x4_t v, uint8_t* const dst,
|
||||||
uint8_t* const dst, int stride) {
|
int stride) {
|
||||||
vst4_lane_u8(dst + 0 * stride, v, 0);
|
vst4_lane_u8(dst + 0 * stride, v, 0);
|
||||||
vst4_lane_u8(dst + 1 * stride, v, 1);
|
vst4_lane_u8(dst + 1 * stride, v, 1);
|
||||||
vst4_lane_u8(dst + 2 * stride, v, 2);
|
vst4_lane_u8(dst + 2 * stride, v, 2);
|
||||||
@@ -260,12 +261,10 @@ static WEBP_INLINE void Store4x16_NEON(const uint8x16_t p1, const uint8x16_t p0,
|
|||||||
const uint8x16_t q0, const uint8x16_t q1,
|
const uint8x16_t q0, const uint8x16_t q1,
|
||||||
uint8_t* const dst, int stride) {
|
uint8_t* const dst, int stride) {
|
||||||
uint8x8x4_t lo, hi;
|
uint8x8x4_t lo, hi;
|
||||||
INIT_VECTOR4(lo,
|
INIT_VECTOR4(lo, vget_low_u8(p1), vget_low_u8(p0), vget_low_u8(q0),
|
||||||
vget_low_u8(p1), vget_low_u8(p0),
|
vget_low_u8(q1));
|
||||||
vget_low_u8(q0), vget_low_u8(q1));
|
INIT_VECTOR4(hi, vget_high_u8(p1), vget_high_u8(p0), vget_high_u8(q0),
|
||||||
INIT_VECTOR4(hi,
|
vget_high_u8(q1));
|
||||||
vget_high_u8(p1), vget_high_u8(p0),
|
|
||||||
vget_high_u8(q0), vget_high_u8(q1));
|
|
||||||
Store4x8_NEON(lo, dst - 2 + 0 * stride, stride);
|
Store4x8_NEON(lo, dst - 2 + 0 * stride, stride);
|
||||||
Store4x8_NEON(hi, dst - 2 + 8 * stride, stride);
|
Store4x8_NEON(hi, dst - 2 + 8 * stride, stride);
|
||||||
}
|
}
|
||||||
@@ -285,9 +284,8 @@ static WEBP_INLINE void Store16x4_NEON(const uint8x16_t p1, const uint8x16_t p0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void Store8x2x2_NEON(const uint8x16_t p0,
|
static WEBP_INLINE void Store8x2x2_NEON(const uint8x16_t p0,
|
||||||
const uint8x16_t q0,
|
const uint8x16_t q0, uint8_t* const u,
|
||||||
uint8_t* const u, uint8_t* const v,
|
uint8_t* const v, int stride) {
|
||||||
int stride) {
|
|
||||||
// p0 and q0 contain the u+v samples packed in low/high halves.
|
// p0 and q0 contain the u+v samples packed in low/high halves.
|
||||||
vst1_u8(u - stride, vget_low_u8(p0));
|
vst1_u8(u - stride, vget_low_u8(p0));
|
||||||
vst1_u8(u, vget_low_u8(q0));
|
vst1_u8(u, vget_low_u8(q0));
|
||||||
@@ -298,9 +296,8 @@ static WEBP_INLINE void Store8x2x2_NEON(const uint8x16_t p0,
|
|||||||
static WEBP_INLINE void Store8x4x2_NEON(const uint8x16_t p1,
|
static WEBP_INLINE void Store8x4x2_NEON(const uint8x16_t p1,
|
||||||
const uint8x16_t p0,
|
const uint8x16_t p0,
|
||||||
const uint8x16_t q0,
|
const uint8x16_t q0,
|
||||||
const uint8x16_t q1,
|
const uint8x16_t q1, uint8_t* const u,
|
||||||
uint8_t* const u, uint8_t* const v,
|
uint8_t* const v, int stride) {
|
||||||
int stride) {
|
|
||||||
// The p1...q1 registers contain the u+v samples packed in low/high halves.
|
// The p1...q1 registers contain the u+v samples packed in low/high halves.
|
||||||
Store8x2x2_NEON(p1, p0, u - stride, v - stride, stride);
|
Store8x2x2_NEON(p1, p0, u - stride, v - stride, stride);
|
||||||
Store8x2x2_NEON(q0, q1, u + stride, v + stride, stride);
|
Store8x2x2_NEON(q0, q1, u + stride, v + stride, stride);
|
||||||
@@ -308,16 +305,17 @@ static WEBP_INLINE void Store8x4x2_NEON(const uint8x16_t p1,
|
|||||||
|
|
||||||
#if !defined(WORK_AROUND_GCC)
|
#if !defined(WORK_AROUND_GCC)
|
||||||
|
|
||||||
#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \
|
#define STORE6_LANE(DST, VAL0, VAL1, LANE) \
|
||||||
|
do { \
|
||||||
vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \
|
vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \
|
||||||
vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \
|
vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \
|
||||||
(DST) += stride; \
|
(DST) += stride; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static WEBP_INLINE void Store6x8x2_NEON(
|
static WEBP_INLINE void Store6x8x2_NEON(
|
||||||
const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0,
|
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 q0, const uint8x16_t q1, const uint8x16_t q2, uint8_t* u,
|
||||||
uint8_t* u, uint8_t* v, int stride) {
|
uint8_t* v, int stride) {
|
||||||
uint8x8x3_t u0, u1, v0, v1;
|
uint8x8x3_t u0, u1, v0, v1;
|
||||||
INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0));
|
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(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2));
|
||||||
@@ -345,16 +343,13 @@ static WEBP_INLINE void Store6x8x2_NEON(
|
|||||||
static WEBP_INLINE void Store4x8x2_NEON(const uint8x16_t p1,
|
static WEBP_INLINE void Store4x8x2_NEON(const uint8x16_t p1,
|
||||||
const uint8x16_t p0,
|
const uint8x16_t p0,
|
||||||
const uint8x16_t q0,
|
const uint8x16_t q0,
|
||||||
const uint8x16_t q1,
|
const uint8x16_t q1, uint8_t* const u,
|
||||||
uint8_t* const u, uint8_t* const v,
|
uint8_t* const v, int stride) {
|
||||||
int stride) {
|
|
||||||
uint8x8x4_t u0, v0;
|
uint8x8x4_t u0, v0;
|
||||||
INIT_VECTOR4(u0,
|
INIT_VECTOR4(u0, vget_low_u8(p1), vget_low_u8(p0), vget_low_u8(q0),
|
||||||
vget_low_u8(p1), vget_low_u8(p0),
|
vget_low_u8(q1));
|
||||||
vget_low_u8(q0), vget_low_u8(q1));
|
INIT_VECTOR4(v0, vget_high_u8(p1), vget_high_u8(p0), vget_high_u8(q0),
|
||||||
INIT_VECTOR4(v0,
|
vget_high_u8(q1));
|
||||||
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 + 0 * stride, u0, 0);
|
||||||
vst4_lane_u8(u - 2 + 1 * stride, u0, 1);
|
vst4_lane_u8(u - 2 + 1 * stride, u0, 1);
|
||||||
vst4_lane_u8(u - 2 + 2 * stride, u0, 2);
|
vst4_lane_u8(u - 2 + 2 * stride, u0, 2);
|
||||||
@@ -397,8 +392,7 @@ static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01,
|
static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01,
|
||||||
const int16x8_t row23,
|
const int16x8_t row23, uint8_t* const dst) {
|
||||||
uint8_t* const dst) {
|
|
||||||
uint32x2_t dst01 = vdup_n_u32(0);
|
uint32x2_t dst01 = vdup_n_u32(0);
|
||||||
uint32x2_t dst23 = vdup_n_u32(0);
|
uint32x2_t dst23 = vdup_n_u32(0);
|
||||||
|
|
||||||
@@ -467,8 +461,7 @@ static int8x16_t GetBaseDelta0_NEON(const int8x16_t p0, const int8x16_t q0) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static void ApplyFilter2NoFlip_NEON(const int8x16_t p0s, const int8x16_t q0s,
|
static void ApplyFilter2NoFlip_NEON(const int8x16_t p0s, const int8x16_t q0s,
|
||||||
const int8x16_t delta,
|
const int8x16_t delta, int8x16_t* const op0,
|
||||||
int8x16_t* const op0,
|
|
||||||
int8x16_t* const oq0) {
|
int8x16_t* const oq0) {
|
||||||
const int8x16_t kCst3 = vdupq_n_s8(0x03);
|
const int8x16_t kCst3 = vdupq_n_s8(0x03);
|
||||||
const int8x16_t kCst4 = vdupq_n_s8(0x04);
|
const int8x16_t kCst4 = vdupq_n_s8(0x04);
|
||||||
@@ -483,8 +476,8 @@ static void ApplyFilter2NoFlip_NEON(const int8x16_t p0s, const int8x16_t q0s,
|
|||||||
#if defined(WEBP_USE_INTRINSICS)
|
#if defined(WEBP_USE_INTRINSICS)
|
||||||
|
|
||||||
static void ApplyFilter2_NEON(const int8x16_t p0s, const int8x16_t q0s,
|
static void ApplyFilter2_NEON(const int8x16_t p0s, const int8x16_t q0s,
|
||||||
const int8x16_t delta,
|
const int8x16_t delta, uint8x16_t* const op0,
|
||||||
uint8x16_t* const op0, uint8x16_t* const oq0) {
|
uint8x16_t* const oq0) {
|
||||||
const int8x16_t kCst3 = vdupq_n_s8(0x03);
|
const int8x16_t kCst3 = vdupq_n_s8(0x03);
|
||||||
const int8x16_t kCst4 = vdupq_n_s8(0x04);
|
const int8x16_t kCst4 = vdupq_n_s8(0x04);
|
||||||
const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3);
|
const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3);
|
||||||
@@ -499,8 +492,8 @@ static void ApplyFilter2_NEON(const int8x16_t p0s, const int8x16_t q0s,
|
|||||||
|
|
||||||
static void DoFilter2_NEON(const uint8x16_t p1, const uint8x16_t p0,
|
static void DoFilter2_NEON(const uint8x16_t p1, const uint8x16_t p0,
|
||||||
const uint8x16_t q0, const uint8x16_t q1,
|
const uint8x16_t q0, const uint8x16_t q1,
|
||||||
const uint8x16_t mask,
|
const uint8x16_t mask, uint8x16_t* const op0,
|
||||||
uint8x16_t* const op0, uint8x16_t* const oq0) {
|
uint8x16_t* const oq0) {
|
||||||
const int8x16_t p1s = FlipSign_NEON(p1);
|
const int8x16_t p1s = FlipSign_NEON(p1);
|
||||||
const int8x16_t p0s = FlipSign_NEON(p0);
|
const int8x16_t p0s = FlipSign_NEON(p0);
|
||||||
const int8x16_t q0s = FlipSign_NEON(q0);
|
const int8x16_t q0s = FlipSign_NEON(q0);
|
||||||
@@ -533,6 +526,7 @@ static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
// Load/Store vertical edge
|
// Load/Store vertical edge
|
||||||
|
// clang-format off
|
||||||
#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \
|
#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 "[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 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \
|
||||||
@@ -600,9 +594,10 @@ static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
|||||||
"vand q9, q9, q11 \n" /* apply filter mask */ \
|
"vand q9, q9, q11 \n" /* apply filter mask */ \
|
||||||
DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \
|
DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \
|
||||||
FLIP_SIGN_BIT2(p0, q0, q10)
|
FLIP_SIGN_BIT2(p0, q0, q10)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
|
"sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
|
||||||
|
|
||||||
"vld1.u8 {q1}, [%[p]], %[stride] \n" // p1
|
"vld1.u8 {q1}, [%[p]], %[stride] \n" // p1
|
||||||
@@ -610,7 +605,7 @@ static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
|||||||
"vld1.u8 {q3}, [%[p]], %[stride] \n" // q0
|
"vld1.u8 {q3}, [%[p]], %[stride] \n" // q0
|
||||||
"vld1.u8 {q12}, [%[p]] \n" // q1
|
"vld1.u8 {q12}, [%[p]] \n" // q1
|
||||||
|
|
||||||
DO_FILTER2(q1, q2, q3, q12, %[thresh])
|
DO_FILTER2(q1, q2, q3, q12, % [thresh]) //
|
||||||
|
|
||||||
"sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
|
"sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
|
||||||
|
|
||||||
@@ -618,12 +613,11 @@ static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
|||||||
"vst1.u8 {q3}, [%[p]] \n" // store oq0
|
"vst1.u8 {q3}, [%[p]] \n" // store oq0
|
||||||
: [p] "+r"(p)
|
: [p] "+r"(p)
|
||||||
: [stride] "r"(stride), [thresh] "r"(thresh)
|
: [stride] "r"(stride), [thresh] "r"(thresh)
|
||||||
: "memory", QRegs
|
: "memory", QRegs);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) {
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"sub r4, %[p], #2 \n" // base1 = p - 2
|
"sub r4, %[p], #2 \n" // base1 = p - 2
|
||||||
"lsl r6, %[stride], #1 \n" // r6 = 2 * stride
|
"lsl r6, %[stride], #1 \n" // r6 = 2 * stride
|
||||||
"add r5, r4, %[stride] \n" // base2 = base1 + stride
|
"add r5, r4, %[stride] \n" // base2 = base1 + stride
|
||||||
@@ -708,12 +702,11 @@ static uint8x16_t NeedsFilter2_NEON(const uint8x16_t p3, const uint8x16_t p2,
|
|||||||
|
|
||||||
// 4-points filter
|
// 4-points filter
|
||||||
|
|
||||||
static void ApplyFilter4_NEON(
|
static void ApplyFilter4_NEON(const int8x16_t p1, const int8x16_t p0,
|
||||||
const int8x16_t p1, const int8x16_t p0,
|
|
||||||
const int8x16_t q0, const int8x16_t q1,
|
const int8x16_t q0, const int8x16_t q1,
|
||||||
const int8x16_t delta0,
|
const int8x16_t delta0, uint8x16_t* const op1,
|
||||||
uint8x16_t* const op1, uint8x16_t* const op0,
|
uint8x16_t* const op0, uint8x16_t* const oq0,
|
||||||
uint8x16_t* const oq0, uint8x16_t* const oq1) {
|
uint8x16_t* const oq1) {
|
||||||
const int8x16_t kCst3 = vdupq_n_s8(0x03);
|
const int8x16_t kCst3 = vdupq_n_s8(0x03);
|
||||||
const int8x16_t kCst4 = vdupq_n_s8(0x04);
|
const int8x16_t kCst4 = vdupq_n_s8(0x04);
|
||||||
const int8x16_t delta1 = vqaddq_s8(delta0, kCst4);
|
const int8x16_t delta1 = vqaddq_s8(delta0, kCst4);
|
||||||
@@ -727,8 +720,7 @@ static void ApplyFilter4_NEON(
|
|||||||
*oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a3)); // clip(q1 - a3)
|
*oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a3)); // clip(q1 - a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DoFilter4_NEON(
|
static void DoFilter4_NEON(const uint8x16_t p1, const uint8x16_t p0,
|
||||||
const uint8x16_t p1, const uint8x16_t p0,
|
|
||||||
const uint8x16_t q0, const uint8x16_t q1,
|
const uint8x16_t q0, const uint8x16_t q1,
|
||||||
const uint8x16_t mask, const uint8x16_t hev_mask,
|
const uint8x16_t mask, const uint8x16_t hev_mask,
|
||||||
uint8x16_t* const op1, uint8x16_t* const op0,
|
uint8x16_t* const op1, uint8x16_t* const op0,
|
||||||
@@ -761,12 +753,13 @@ static void DoFilter4_NEON(
|
|||||||
|
|
||||||
// 6-points filter
|
// 6-points filter
|
||||||
|
|
||||||
static void ApplyFilter6_NEON(
|
static void ApplyFilter6_NEON(const int8x16_t p2, const int8x16_t p1,
|
||||||
const int8x16_t p2, const int8x16_t p1, const int8x16_t p0,
|
const int8x16_t p0, const int8x16_t q0,
|
||||||
const int8x16_t q0, const int8x16_t q1, const int8x16_t q2,
|
const int8x16_t q1, const int8x16_t q2,
|
||||||
const int8x16_t delta,
|
const int8x16_t delta, uint8x16_t* const op2,
|
||||||
uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0,
|
uint8x16_t* const op1, uint8x16_t* const op0,
|
||||||
uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) {
|
uint8x16_t* const oq0, uint8x16_t* const oq1,
|
||||||
|
uint8x16_t* const oq2) {
|
||||||
// We have to compute: X = (9*a+63) >> 7, Y = (18*a+63)>>7, Z = (27*a+63) >> 7
|
// We have to compute: X = (9*a+63) >> 7, Y = (18*a+63)>>7, Z = (27*a+63) >> 7
|
||||||
// Turns out, there's a common sub-expression S=9 * a - 1 that can be used
|
// Turns out, there's a common sub-expression S=9 * a - 1 that can be used
|
||||||
// with the special vqrshrn_n_s16 rounding-shift-and-narrow instruction:
|
// with the special vqrshrn_n_s16 rounding-shift-and-narrow instruction:
|
||||||
@@ -798,12 +791,13 @@ static void ApplyFilter6_NEON(
|
|||||||
*op2 = FlipSignBack_NEON(vqaddq_s8(p2, a3)); // clip(p2 + a3)
|
*op2 = FlipSignBack_NEON(vqaddq_s8(p2, a3)); // clip(p2 + a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DoFilter6_NEON(
|
static void DoFilter6_NEON(const uint8x16_t p2, const uint8x16_t p1,
|
||||||
const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0,
|
const uint8x16_t p0, const uint8x16_t q0,
|
||||||
const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2,
|
const uint8x16_t q1, const uint8x16_t q2,
|
||||||
const uint8x16_t mask, const uint8x16_t hev_mask,
|
const uint8x16_t mask, const uint8x16_t hev_mask,
|
||||||
uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0,
|
uint8x16_t* const op2, uint8x16_t* const op1,
|
||||||
uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) {
|
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
|
// This is a fused version of DoFilter2() calling ApplyFilter2 directly
|
||||||
const int8x16_t p2s = FlipSign_NEON(p2);
|
const int8x16_t p2s = FlipSign_NEON(p2);
|
||||||
const int8x16_t p1s = FlipSign_NEON(p1);
|
const int8x16_t p1s = FlipSign_NEON(p1);
|
||||||
@@ -827,41 +821,41 @@ static void DoFilter6_NEON(
|
|||||||
const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask);
|
const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask);
|
||||||
const int8x16_t complex_lf_delta =
|
const int8x16_t complex_lf_delta =
|
||||||
vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask));
|
vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask));
|
||||||
ApplyFilter6_NEON(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta,
|
ApplyFilter6_NEON(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, op2, op1,
|
||||||
op2, op1, op0, oq0, oq1, oq2);
|
op0, oq0, oq1, oq2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// on macroblock edges
|
// on macroblock edges
|
||||||
|
|
||||||
static void VFilter16_NEON(uint8_t* p, int stride,
|
static void VFilter16_NEON(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
Load16x8_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
Load16x8_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
||||||
{
|
{
|
||||||
const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3,
|
const uint8x16_t mask =
|
||||||
ithresh, thresh);
|
NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
|
||||||
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
||||||
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
||||||
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask,
|
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, &op2, &op1, &op0,
|
||||||
&op2, &op1, &op0, &oq0, &oq1, &oq2);
|
&oq0, &oq1, &oq2);
|
||||||
Store16x2_NEON(op2, op1, p - 2 * stride, stride);
|
Store16x2_NEON(op2, op1, p - 2 * stride, stride);
|
||||||
Store16x2_NEON(op0, oq0, p + 0 * stride, stride);
|
Store16x2_NEON(op0, oq0, p + 0 * stride, stride);
|
||||||
Store16x2_NEON(oq1, oq2, p + 2 * stride, stride);
|
Store16x2_NEON(oq1, oq2, p + 2 * stride, stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16_NEON(uint8_t* p, int stride,
|
static void HFilter16_NEON(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
Load8x16_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
Load8x16_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
||||||
{
|
{
|
||||||
const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3,
|
const uint8x16_t mask =
|
||||||
ithresh, thresh);
|
NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
|
||||||
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
||||||
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
||||||
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask,
|
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, &op2, &op1, &op0,
|
||||||
&op2, &op1, &op0, &oq0, &oq1, &oq2);
|
&oq0, &oq1, &oq2);
|
||||||
Store2x16_NEON(op2, op1, p - 2, stride);
|
Store2x16_NEON(op2, op1, p - 2, stride);
|
||||||
Store2x16_NEON(op0, oq0, p + 0, stride);
|
Store2x16_NEON(op0, oq0, p + 0, stride);
|
||||||
Store2x16_NEON(oq1, oq2, p + 2, stride);
|
Store2x16_NEON(oq1, oq2, p + 2, stride);
|
||||||
@@ -869,8 +863,8 @@ static void HFilter16_NEON(uint8_t* p, int stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on three inner edges
|
// on three inner edges
|
||||||
static void VFilter16i_NEON(uint8_t* p, int stride,
|
static void VFilter16i_NEON(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
uint32_t k;
|
uint32_t k;
|
||||||
uint8x16_t p3, p2, p1, p0;
|
uint8x16_t p3, p2, p1, p0;
|
||||||
Load16x4_NEON(p + 2 * stride, stride, &p3, &p2, &p1, &p0);
|
Load16x4_NEON(p + 2 * stride, stride, &p3, &p2, &p1, &p0);
|
||||||
@@ -893,8 +887,8 @@ static void VFilter16i_NEON(uint8_t* p, int stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(WORK_AROUND_GCC)
|
#if !defined(WORK_AROUND_GCC)
|
||||||
static void HFilter16i_NEON(uint8_t* p, int stride,
|
static void HFilter16i_NEON(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
uint32_t k;
|
uint32_t k;
|
||||||
uint8x16_t p3, p2, p1, p0;
|
uint8x16_t p3, p2, p1, p0;
|
||||||
Load4x16_NEON(p + 2, stride, &p3, &p2, &p1, &p0);
|
Load4x16_NEON(p + 2, stride, &p3, &p2, &p1, &p0);
|
||||||
@@ -921,27 +915,27 @@ static void VFilter8_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
|||||||
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
||||||
{
|
{
|
||||||
const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3,
|
const uint8x16_t mask =
|
||||||
ithresh, thresh);
|
NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
|
||||||
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
||||||
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
||||||
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask,
|
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, &op2, &op1, &op0,
|
||||||
&op2, &op1, &op0, &oq0, &oq1, &oq2);
|
&oq0, &oq1, &oq2);
|
||||||
Store8x2x2_NEON(op2, op1, u - 2 * stride, v - 2 * stride, stride);
|
Store8x2x2_NEON(op2, op1, u - 2 * stride, v - 2 * stride, stride);
|
||||||
Store8x2x2_NEON(op0, oq0, u + 0 * stride, v + 0 * stride, stride);
|
Store8x2x2_NEON(op0, oq0, u + 0 * stride, v + 0 * stride, stride);
|
||||||
Store8x2x2_NEON(oq1, oq2, u + 2 * stride, v + 2 * stride, stride);
|
Store8x2x2_NEON(oq1, oq2, u + 2 * stride, v + 2 * stride, stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void VFilter8i_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
static void VFilter8i_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
||||||
int stride,
|
int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
u += 4 * stride;
|
u += 4 * stride;
|
||||||
v += 4 * stride;
|
v += 4 * stride;
|
||||||
Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
||||||
{
|
{
|
||||||
const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3,
|
const uint8x16_t mask =
|
||||||
ithresh, thresh);
|
NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
|
||||||
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
||||||
uint8x16_t op1, op0, oq0, oq1;
|
uint8x16_t op1, op0, oq0, oq1;
|
||||||
DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
|
DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
|
||||||
@@ -955,26 +949,26 @@ static void HFilter8_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
|||||||
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
||||||
{
|
{
|
||||||
const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3,
|
const uint8x16_t mask =
|
||||||
ithresh, thresh);
|
NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
|
||||||
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
||||||
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
uint8x16_t op2, op1, op0, oq0, oq1, oq2;
|
||||||
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask,
|
DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, &op2, &op1, &op0,
|
||||||
&op2, &op1, &op0, &oq0, &oq1, &oq2);
|
&oq0, &oq1, &oq2);
|
||||||
Store6x8x2_NEON(op2, op1, op0, oq0, oq1, oq2, u, v, stride);
|
Store6x8x2_NEON(op2, op1, op0, oq0, oq1, oq2, u, v, stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter8i_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
static void HFilter8i_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
||||||
int stride,
|
int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
u += 4;
|
u += 4;
|
||||||
v += 4;
|
v += 4;
|
||||||
Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
|
||||||
{
|
{
|
||||||
const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3,
|
const uint8x16_t mask =
|
||||||
ithresh, thresh);
|
NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
|
||||||
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh);
|
||||||
uint8x16_t op1, op0, oq0, oq1;
|
uint8x16_t op1, op0, oq0, oq1;
|
||||||
DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
|
DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
|
||||||
@@ -1058,9 +1052,9 @@ static void TransformOne_NEON(const int16_t* WEBP_RESTRICT in,
|
|||||||
uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
const int kBPS = BPS;
|
const int kBPS = BPS;
|
||||||
// kC1, kC2. Padded because vld1.16 loads 8 bytes
|
// kC1, kC2. Padded because vld1.16 loads 8 bytes
|
||||||
const int16_t constants[4] = { kC1, kC2, 0, 0 };
|
const int16_t constants[4] = {kC1, kC2, 0, 0};
|
||||||
/* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */
|
/* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"vld1.16 {q1, q2}, [%[in]] \n"
|
"vld1.16 {q1, q2}, [%[in]] \n"
|
||||||
"vld1.16 {d0}, [%[constants]] \n"
|
"vld1.16 {d0}, [%[constants]] \n"
|
||||||
|
|
||||||
@@ -1204,12 +1198,17 @@ static void TransformDC_NEON(const int16_t* WEBP_RESTRICT in,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define STORE_WHT(dst, col, rows) do { \
|
#define STORE_WHT(dst, col, rows) \
|
||||||
*dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \
|
do { \
|
||||||
*dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \
|
*dst = vgetq_lane_s32(rows.val[0], col); \
|
||||||
*dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \
|
(dst) += 16; \
|
||||||
*dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \
|
*dst = vgetq_lane_s32(rows.val[1], col); \
|
||||||
} while (0)
|
(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_NEON(const int16_t* WEBP_RESTRICT in,
|
static void TransformWHT_NEON(const int16_t* WEBP_RESTRICT in,
|
||||||
int16_t* WEBP_RESTRICT out) {
|
int16_t* WEBP_RESTRICT out) {
|
||||||
@@ -1270,10 +1269,9 @@ static void TransformAC3_NEON(const int16_t* WEBP_RESTRICT in,
|
|||||||
const int16x4_t d4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL1(in[4]));
|
const int16x4_t d4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL1(in[4]));
|
||||||
const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
|
const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
|
||||||
const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
|
const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
|
||||||
const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 |
|
const uint64_t cd =
|
||||||
(uint64_t)( c1 & 0xffff) << 16 |
|
(uint64_t)(d1 & 0xffff) << 0 | (uint64_t)(c1 & 0xffff) << 16 |
|
||||||
(uint64_t)(-c1 & 0xffff) << 32 |
|
(uint64_t)(-c1 & 0xffff) << 32 | (uint64_t)(-d1 & 0xffff) << 48;
|
||||||
(uint64_t)(-d1 & 0xffff) << 48;
|
|
||||||
const int16x4_t CD = vcreate_s16(cd);
|
const int16x4_t CD = vcreate_s16(cd);
|
||||||
const int16x4_t B = vqadd_s16(A, 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 m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4));
|
||||||
|
|||||||
@@ -248,9 +248,8 @@ static void TransformAC3_SSE2(const int16_t* WEBP_RESTRICT in,
|
|||||||
// Loop Filter (Paragraph 15)
|
// Loop Filter (Paragraph 15)
|
||||||
|
|
||||||
// Compute abs(p - q) = subs(p - q) OR subs(q - p)
|
// Compute abs(p - q) = subs(p - q) OR subs(q - p)
|
||||||
#define MM_ABS(p, q) _mm_or_si128( \
|
#define MM_ABS(p, q) \
|
||||||
_mm_subs_epu8((q), (p)), \
|
_mm_or_si128(_mm_subs_epu8((q), (p)), _mm_subs_epu8((p), (q)))
|
||||||
_mm_subs_epu8((p), (q)))
|
|
||||||
|
|
||||||
// Shift each byte of "x" by 3 bits while preserving by the sign bit.
|
// Shift each byte of "x" by 3 bits while preserving by the sign bit.
|
||||||
static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) {
|
static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) {
|
||||||
@@ -262,22 +261,24 @@ static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) {
|
|||||||
*x = _mm_packs_epi16(lo_1, hi_1);
|
*x = _mm_packs_epi16(lo_1, hi_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLIP_SIGN_BIT2(a, b) do { \
|
#define FLIP_SIGN_BIT2(a, b) \
|
||||||
|
do { \
|
||||||
(a) = _mm_xor_si128(a, sign_bit); \
|
(a) = _mm_xor_si128(a, sign_bit); \
|
||||||
(b) = _mm_xor_si128(b, sign_bit); \
|
(b) = _mm_xor_si128(b, sign_bit); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define FLIP_SIGN_BIT4(a, b, c, d) do { \
|
#define FLIP_SIGN_BIT4(a, b, c, d) \
|
||||||
|
do { \
|
||||||
FLIP_SIGN_BIT2(a, b); \
|
FLIP_SIGN_BIT2(a, b); \
|
||||||
FLIP_SIGN_BIT2(c, d); \
|
FLIP_SIGN_BIT2(c, d); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// input/output is uint8_t
|
// input/output is uint8_t
|
||||||
static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1,
|
static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1,
|
||||||
const __m128i* const p0,
|
const __m128i* const p0,
|
||||||
const __m128i* const q0,
|
const __m128i* const q0,
|
||||||
const __m128i* const q1,
|
const __m128i* const q1, int hev_thresh,
|
||||||
int hev_thresh, __m128i* const not_hev) {
|
__m128i* const not_hev) {
|
||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
const __m128i t_1 = MM_ABS(*p1, *p0);
|
const __m128i t_1 = MM_ABS(*p1, *p0);
|
||||||
const __m128i t_2 = MM_ABS(*q1, *q0);
|
const __m128i t_2 = MM_ABS(*q1, *q0);
|
||||||
@@ -339,8 +340,8 @@ static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi,
|
|||||||
static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1,
|
static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1,
|
||||||
const __m128i* const p0,
|
const __m128i* const p0,
|
||||||
const __m128i* const q0,
|
const __m128i* const q0,
|
||||||
const __m128i* const q1,
|
const __m128i* const q1, int thresh,
|
||||||
int thresh, __m128i* const mask) {
|
__m128i* const mask) {
|
||||||
const __m128i m_thresh = _mm_set1_epi8((char)thresh);
|
const __m128i m_thresh = _mm_set1_epi8((char)thresh);
|
||||||
const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
|
const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
|
||||||
const __m128i kFE = _mm_set1_epi8((char)0xFE);
|
const __m128i kFE = _mm_set1_epi8((char)0xFE);
|
||||||
@@ -503,8 +504,7 @@ static WEBP_INLINE void Load8x4_SSE2(const uint8_t* const b, int stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0,
|
static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0,
|
||||||
const uint8_t* const r8,
|
const uint8_t* const r8, int stride,
|
||||||
int stride,
|
|
||||||
__m128i* const p1, __m128i* const p0,
|
__m128i* const p1, __m128i* const p0,
|
||||||
__m128i* const q0, __m128i* const q1) {
|
__m128i* const q0, __m128i* const q1) {
|
||||||
// Assume the pixels around the edge (|) are numbered as follows
|
// Assume the pixels around the edge (|) are numbered as follows
|
||||||
@@ -539,8 +539,8 @@ static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void Store4x4_SSE2(__m128i* const x,
|
static WEBP_INLINE void Store4x4_SSE2(__m128i* const x, uint8_t* dst,
|
||||||
uint8_t* dst, int stride) {
|
int stride) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; ++i, dst += stride) {
|
for (i = 0; i < 4; ++i, dst += stride) {
|
||||||
WebPInt32ToMem(dst, _mm_cvtsi128_si32(*x));
|
WebPInt32ToMem(dst, _mm_cvtsi128_si32(*x));
|
||||||
@@ -552,9 +552,8 @@ static WEBP_INLINE void Store4x4_SSE2(__m128i* const x,
|
|||||||
static WEBP_INLINE void Store16x4_SSE2(const __m128i* const p1,
|
static WEBP_INLINE void Store16x4_SSE2(const __m128i* const p1,
|
||||||
const __m128i* const p0,
|
const __m128i* const p0,
|
||||||
const __m128i* const q0,
|
const __m128i* const q0,
|
||||||
const __m128i* const q1,
|
const __m128i* const q1, uint8_t* r0,
|
||||||
uint8_t* r0, uint8_t* r8,
|
uint8_t* r8, int stride) {
|
||||||
int stride) {
|
|
||||||
__m128i t1, p1_s, p0_s, q0_s, q1_s;
|
__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
|
// p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
|
||||||
@@ -636,50 +635,55 @@ static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Complex In-loop filtering (Paragraph 15.3)
|
// Complex In-loop filtering (Paragraph 15.3)
|
||||||
|
|
||||||
#define MAX_DIFF1(p3, p2, p1, p0, m) do { \
|
#define MAX_DIFF1(p3, p2, p1, p0, m) \
|
||||||
|
do { \
|
||||||
(m) = MM_ABS(p1, p0); \
|
(m) = MM_ABS(p1, p0); \
|
||||||
(m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \
|
(m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \
|
||||||
(m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \
|
(m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define MAX_DIFF2(p3, p2, p1, p0, m) do { \
|
#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(p1, p0)); \
|
||||||
(m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \
|
(m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \
|
||||||
(m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \
|
(m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) do { \
|
#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) \
|
||||||
|
do { \
|
||||||
(e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \
|
(e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \
|
||||||
(e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \
|
(e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \
|
||||||
(e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \
|
(e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \
|
||||||
(e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \
|
(e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LOADUV_H_EDGE(p, u, v, stride) do { \
|
#define LOADUV_H_EDGE(p, u, v, stride) \
|
||||||
|
do { \
|
||||||
const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
|
const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
|
||||||
const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \
|
const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \
|
||||||
(p) = _mm_unpacklo_epi64(U, V); \
|
(p) = _mm_unpacklo_epi64(U, V); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) do { \
|
#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) \
|
||||||
|
do { \
|
||||||
LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \
|
LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \
|
||||||
LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \
|
LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \
|
||||||
LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \
|
LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \
|
||||||
LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \
|
LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define STOREUV(p, u, v, stride) do { \
|
#define STOREUV(p, u, v, stride) \
|
||||||
|
do { \
|
||||||
_mm_storel_epi64((__m128i*)&(u)[(stride)], p); \
|
_mm_storel_epi64((__m128i*)&(u)[(stride)], p); \
|
||||||
(p) = _mm_srli_si128(p, 8); \
|
(p) = _mm_srli_si128(p, 8); \
|
||||||
_mm_storel_epi64((__m128i*)&(v)[(stride)], p); \
|
_mm_storel_epi64((__m128i*)&(v)[(stride)], p); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1,
|
static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1,
|
||||||
const __m128i* const p0,
|
const __m128i* const p0,
|
||||||
const __m128i* const q0,
|
const __m128i* const q0,
|
||||||
const __m128i* const q1,
|
const __m128i* const q1, int thresh,
|
||||||
int thresh, int ithresh,
|
int ithresh, __m128i* const mask) {
|
||||||
__m128i* const mask) {
|
|
||||||
const __m128i it = _mm_set1_epi8(ithresh);
|
const __m128i it = _mm_set1_epi8(ithresh);
|
||||||
const __m128i diff = _mm_subs_epu8(*mask, it);
|
const __m128i diff = _mm_subs_epu8(*mask, it);
|
||||||
const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128());
|
const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128());
|
||||||
@@ -689,8 +693,8 @@ static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on macroblock edges
|
// on macroblock edges
|
||||||
static void VFilter16_SSE2(uint8_t* p, int stride,
|
static void VFilter16_SSE2(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
__m128i t1;
|
__m128i t1;
|
||||||
__m128i mask;
|
__m128i mask;
|
||||||
__m128i p2, p1, p0, q0, q1, q2;
|
__m128i p2, p1, p0, q0, q1, q2;
|
||||||
@@ -715,8 +719,8 @@ static void VFilter16_SSE2(uint8_t* p, int stride,
|
|||||||
_mm_storeu_si128((__m128i*)&p[+2 * stride], q2);
|
_mm_storeu_si128((__m128i*)&p[+2 * stride], q2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16_SSE2(uint8_t* p, int stride,
|
static void HFilter16_SSE2(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
__m128i mask;
|
__m128i mask;
|
||||||
__m128i p3, p2, p1, p0, q0, q1, q2, q3;
|
__m128i p3, p2, p1, p0, q0, q1, q2, q3;
|
||||||
|
|
||||||
@@ -735,8 +739,8 @@ static void HFilter16_SSE2(uint8_t* p, int stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// on three inner edges
|
// on three inner edges
|
||||||
static void VFilter16i_SSE2(uint8_t* p, int stride,
|
static void VFilter16i_SSE2(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
__m128i p3, p2, p1, p0; // loop invariants
|
__m128i p3, p2, p1, p0; // loop invariants
|
||||||
|
|
||||||
@@ -768,8 +772,8 @@ static void VFilter16i_SSE2(uint8_t* p, int stride,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter16i_SSE2(uint8_t* p, int stride,
|
static void HFilter16i_SSE2(uint8_t* p, int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
int k;
|
int k;
|
||||||
__m128i p3, p2, p1, p0; // loop invariants
|
__m128i p3, p2, p1, p0; // loop invariants
|
||||||
|
|
||||||
@@ -843,8 +847,8 @@ static void HFilter8_SSE2(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void VFilter8i_SSE2(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
static void VFilter8i_SSE2(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
||||||
int stride,
|
int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
__m128i mask;
|
__m128i mask;
|
||||||
__m128i t1, t2, p1, p0, q0, q1;
|
__m128i t1, t2, p1, p0, q0, q1;
|
||||||
|
|
||||||
@@ -870,8 +874,8 @@ static void VFilter8i_SSE2(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void HFilter8i_SSE2(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
static void HFilter8i_SSE2(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
|
||||||
int stride,
|
int stride, int thresh, int ithresh,
|
||||||
int thresh, int ithresh, int hev_thresh) {
|
int hev_thresh) {
|
||||||
__m128i mask;
|
__m128i mask;
|
||||||
__m128i t1, t2, p1, p0, q0, q1;
|
__m128i t1, t2, p1, p0, q0, q1;
|
||||||
Load16x4_SSE2(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
|
Load16x4_SSE2(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
|
||||||
@@ -930,7 +934,7 @@ static void LD4_SSE2(uint8_t* dst) { // Down-Left
|
|||||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
|
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
|
||||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||||
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
|
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(abcdefg));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
||||||
@@ -951,8 +955,8 @@ static void VR4_SSE2(uint8_t* dst) { // Vertical-Right
|
|||||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
|
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
|
||||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||||
const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
|
const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(abcd));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(efgh));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
|
||||||
|
|
||||||
@@ -977,8 +981,8 @@ static void VL4_SSE2(uint8_t* dst) { // Vertical-Left
|
|||||||
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
|
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
|
||||||
const uint32_t extra_out =
|
const uint32_t extra_out =
|
||||||
(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
|
(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(avg1));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(avg4));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
|
||||||
|
|
||||||
@@ -1004,7 +1008,7 @@ static void RD4_SSE2(uint8_t* dst) { // Down-right
|
|||||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
|
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
|
||||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||||
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
|
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(abcdefg));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#include <smmintrin.h>
|
#include <smmintrin.h>
|
||||||
|
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/dec/vp8i_dec.h"
|
#include "src/dec/vp8i_dec.h"
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/utils/utils.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
static void HE16_SSE41(uint8_t* dst) { // horizontal
|
static void HE16_SSE41(uint8_t* dst) { // horizontal
|
||||||
int j;
|
int j;
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ extern "C" {
|
|||||||
#define WEBP_RESTRICT
|
#define WEBP_RESTRICT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Init stub generator
|
// Init stub generator
|
||||||
|
|
||||||
@@ -95,8 +94,7 @@ extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16;
|
|||||||
|
|
||||||
// Compute the average (DC) of four 4x4 blocks.
|
// Compute the average (DC) of four 4x4 blocks.
|
||||||
// Each sub-4x4 block #i sum is stored in dc[i].
|
// Each sub-4x4 block #i sum is stored in dc[i].
|
||||||
typedef void (*VP8MeanMetric)(const uint8_t* WEBP_RESTRICT ref,
|
typedef void (*VP8MeanMetric)(const uint8_t* WEBP_RESTRICT ref, uint32_t dc[4]);
|
||||||
uint32_t dc[4]);
|
|
||||||
extern VP8MeanMetric VP8Mean16x4;
|
extern VP8MeanMetric VP8Mean16x4;
|
||||||
|
|
||||||
typedef void (*VP8BlockCopy)(const uint8_t* WEBP_RESTRICT src,
|
typedef void (*VP8BlockCopy)(const uint8_t* WEBP_RESTRICT src,
|
||||||
@@ -132,8 +130,8 @@ typedef struct {
|
|||||||
int last_non_zero;
|
int last_non_zero;
|
||||||
} VP8Histogram;
|
} VP8Histogram;
|
||||||
typedef void (*VP8CHisto)(const uint8_t* WEBP_RESTRICT ref,
|
typedef void (*VP8CHisto)(const uint8_t* WEBP_RESTRICT ref,
|
||||||
const uint8_t* WEBP_RESTRICT pred,
|
const uint8_t* WEBP_RESTRICT pred, int start_block,
|
||||||
int start_block, int end_block,
|
int end_block,
|
||||||
VP8Histogram* WEBP_RESTRICT const histo);
|
VP8Histogram* WEBP_RESTRICT const histo);
|
||||||
extern VP8CHisto VP8CollectHistogram;
|
extern VP8CHisto VP8CollectHistogram;
|
||||||
// General-purpose util function to help VP8CollectHistogram().
|
// General-purpose util function to help VP8CollectHistogram().
|
||||||
@@ -248,8 +246,8 @@ extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges
|
|||||||
extern VP8SimpleFilterFunc VP8SimpleHFilter16i;
|
extern VP8SimpleFilterFunc VP8SimpleHFilter16i;
|
||||||
|
|
||||||
// regular filter (on both macroblock edges and inner edges)
|
// regular filter (on both macroblock edges and inner edges)
|
||||||
typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride,
|
typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, int thresh,
|
||||||
int thresh, int ithresh, int hev_t);
|
int ithresh, int hev_t);
|
||||||
typedef void (*VP8ChromaFilterFunc)(uint8_t* WEBP_RESTRICT u,
|
typedef void (*VP8ChromaFilterFunc)(uint8_t* WEBP_RESTRICT u,
|
||||||
uint8_t* WEBP_RESTRICT v, int stride,
|
uint8_t* WEBP_RESTRICT v, int stride,
|
||||||
int thresh, int ithresh, int hev_t);
|
int thresh, int ithresh, int hev_t);
|
||||||
@@ -344,8 +342,8 @@ extern void (*WebPConvertARGBToY)(const uint32_t* WEBP_RESTRICT argb,
|
|||||||
// the U/V one.
|
// the U/V one.
|
||||||
extern void (*WebPConvertARGBToUV)(const uint32_t* WEBP_RESTRICT argb,
|
extern void (*WebPConvertARGBToUV)(const uint32_t* WEBP_RESTRICT argb,
|
||||||
uint8_t* WEBP_RESTRICT u,
|
uint8_t* WEBP_RESTRICT u,
|
||||||
uint8_t* WEBP_RESTRICT v,
|
uint8_t* WEBP_RESTRICT v, int src_width,
|
||||||
int src_width, int do_store);
|
int do_store);
|
||||||
|
|
||||||
// Convert a row of accumulated (four-values) of rgba32 toward U/V
|
// Convert a row of accumulated (four-values) of rgba32 toward U/V
|
||||||
extern void (*WebPConvertRGBA32ToUV)(const uint16_t* WEBP_RESTRICT rgb,
|
extern void (*WebPConvertRGBA32ToUV)(const uint16_t* WEBP_RESTRICT rgb,
|
||||||
@@ -361,8 +359,8 @@ extern void (*WebPConvertBGRToY)(const uint8_t* WEBP_RESTRICT bgr,
|
|||||||
// used for plain-C fallback.
|
// used for plain-C fallback.
|
||||||
extern void WebPConvertARGBToUV_C(const uint32_t* WEBP_RESTRICT argb,
|
extern void WebPConvertARGBToUV_C(const uint32_t* WEBP_RESTRICT argb,
|
||||||
uint8_t* WEBP_RESTRICT u,
|
uint8_t* WEBP_RESTRICT u,
|
||||||
uint8_t* WEBP_RESTRICT v,
|
uint8_t* WEBP_RESTRICT v, int src_width,
|
||||||
int src_width, int do_store);
|
int do_store);
|
||||||
extern void WebPConvertRGBA32ToUV_C(const uint16_t* WEBP_RESTRICT rgb,
|
extern void WebPConvertRGBA32ToUV_C(const uint16_t* WEBP_RESTRICT rgb,
|
||||||
uint8_t* WEBP_RESTRICT u,
|
uint8_t* WEBP_RESTRICT u,
|
||||||
uint8_t* WEBP_RESTRICT v, int width);
|
uint8_t* WEBP_RESTRICT v, int width);
|
||||||
@@ -403,8 +401,7 @@ extern void WebPRescalerExportRowExpand_C(struct WebPRescaler* const wrk);
|
|||||||
extern void WebPRescalerExportRowShrink_C(struct WebPRescaler* const wrk);
|
extern void WebPRescalerExportRowShrink_C(struct WebPRescaler* const wrk);
|
||||||
|
|
||||||
// Main entry calls:
|
// Main entry calls:
|
||||||
extern void WebPRescalerImportRow(
|
extern void WebPRescalerImportRow(struct WebPRescaler* WEBP_RESTRICT const wrk,
|
||||||
struct WebPRescaler* WEBP_RESTRICT const wrk,
|
|
||||||
const uint8_t* WEBP_RESTRICT src);
|
const uint8_t* WEBP_RESTRICT src);
|
||||||
// Export one row (starting at x_out position) from rescaler.
|
// Export one row (starting at x_out position) from rescaler.
|
||||||
extern void WebPRescalerExportRow(struct WebPRescaler* const wrk);
|
extern void WebPRescalerExportRow(struct WebPRescaler* const wrk);
|
||||||
@@ -417,12 +414,12 @@ void WebPRescalerDspInit(void);
|
|||||||
|
|
||||||
// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h.
|
// 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).
|
// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last).
|
||||||
extern void (*WebPApplyAlphaMultiply)(
|
extern void (*WebPApplyAlphaMultiply)(uint8_t* rgba, int alpha_first, int w,
|
||||||
uint8_t* rgba, int alpha_first, int w, int h, int stride);
|
int h, int stride);
|
||||||
|
|
||||||
// Same, buf specifically for RGBA4444 format
|
// Same, buf specifically for RGBA4444 format
|
||||||
extern void (*WebPApplyAlphaMultiply4444)(
|
extern void (*WebPApplyAlphaMultiply4444)(uint8_t* rgba4444, int w, int h,
|
||||||
uint8_t* rgba4444, int w, int h, int stride);
|
int stride);
|
||||||
|
|
||||||
// Dispatch the values from alpha[] plane to the ARGB destination 'dst'.
|
// Dispatch the values from alpha[] plane to the ARGB destination 'dst'.
|
||||||
// Returns true if alpha[] plane has non-trivial values different from 0xff.
|
// Returns true if alpha[] plane has non-trivial values different from 0xff.
|
||||||
@@ -442,8 +439,7 @@ extern void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT alpha,
|
|||||||
// Returns true if there's only trivial 0xff alpha values.
|
// Returns true if there's only trivial 0xff alpha values.
|
||||||
extern int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT argb,
|
extern int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT argb,
|
||||||
int argb_stride, int width, int height,
|
int argb_stride, int width, int height,
|
||||||
uint8_t* WEBP_RESTRICT alpha,
|
uint8_t* WEBP_RESTRICT alpha, int alpha_stride);
|
||||||
int alpha_stride);
|
|
||||||
|
|
||||||
// Extract the green values from 32b values in argb[] and pack them into alpha[]
|
// Extract the green values from 32b values in argb[] and pack them into alpha[]
|
||||||
// (this is the opposite of WebPDispatchAlphaToGreen).
|
// (this is the opposite of WebPDispatchAlphaToGreen).
|
||||||
@@ -462,8 +458,8 @@ void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
|
|||||||
|
|
||||||
// Same for a row of single values, with side alpha values.
|
// Same for a row of single values, with side alpha values.
|
||||||
extern void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
|
extern void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
|
||||||
const uint8_t* WEBP_RESTRICT const alpha,
|
const uint8_t* WEBP_RESTRICT const alpha, int width,
|
||||||
int width, int inverse);
|
int inverse);
|
||||||
|
|
||||||
// Same a WebPMultRow(), but for several 'num_rows' rows.
|
// Same a WebPMultRow(), but for several 'num_rows' rows.
|
||||||
void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
|
void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
|
||||||
@@ -472,8 +468,8 @@ void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
|
|||||||
|
|
||||||
// Plain-C versions, used as fallback by some implementations.
|
// Plain-C versions, used as fallback by some implementations.
|
||||||
void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
|
void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
|
||||||
const uint8_t* WEBP_RESTRICT const alpha,
|
const uint8_t* WEBP_RESTRICT const alpha, int width,
|
||||||
int width, int inverse);
|
int inverse);
|
||||||
void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse);
|
void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse);
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
@@ -481,15 +477,15 @@ void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse);
|
|||||||
extern void (*WebPPackARGB)(const uint8_t* WEBP_RESTRICT a,
|
extern void (*WebPPackARGB)(const uint8_t* WEBP_RESTRICT a,
|
||||||
const uint8_t* WEBP_RESTRICT r,
|
const uint8_t* WEBP_RESTRICT r,
|
||||||
const uint8_t* WEBP_RESTRICT g,
|
const uint8_t* WEBP_RESTRICT g,
|
||||||
const uint8_t* WEBP_RESTRICT b,
|
const uint8_t* WEBP_RESTRICT b, int len,
|
||||||
int len, uint32_t* WEBP_RESTRICT out);
|
uint32_t* WEBP_RESTRICT out);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order.
|
// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order.
|
||||||
extern void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
|
extern void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
|
||||||
const uint8_t* WEBP_RESTRICT g,
|
const uint8_t* WEBP_RESTRICT g,
|
||||||
const uint8_t* WEBP_RESTRICT b,
|
const uint8_t* WEBP_RESTRICT b, int len, int step,
|
||||||
int len, int step, uint32_t* WEBP_RESTRICT out);
|
uint32_t* WEBP_RESTRICT out);
|
||||||
|
|
||||||
// This function returns true if src[i] contains a value different from 0xff.
|
// This function returns true if src[i] contains a value different from 0xff.
|
||||||
extern int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
extern int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
||||||
@@ -514,8 +510,8 @@ typedef enum { // Filter types.
|
|||||||
WEBP_FILTER_FAST
|
WEBP_FILTER_FAST
|
||||||
} WEBP_FILTER_TYPE;
|
} WEBP_FILTER_TYPE;
|
||||||
|
|
||||||
typedef void (*WebPFilterFunc)(const uint8_t* WEBP_RESTRICT in,
|
typedef void (*WebPFilterFunc)(const uint8_t* WEBP_RESTRICT in, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT out);
|
uint8_t* WEBP_RESTRICT out);
|
||||||
// In-place un-filtering.
|
// In-place un-filtering.
|
||||||
// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'.
|
// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'.
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ static WEBP_INLINE uint8_t clip_8b(int v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
static WEBP_INLINE int clip_max(int v, int max) {
|
static WEBP_INLINE int clip_max(int v, int max) { return (v > max) ? max : v; }
|
||||||
return (v > max) ? max : v;
|
|
||||||
}
|
|
||||||
#endif // !WEBP_NEON_OMIT_C_CODE
|
#endif // !WEBP_NEON_OMIT_C_CODE
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -68,7 +66,7 @@ static void CollectHistogram_C(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
int start_block, int end_block,
|
int start_block, int end_block,
|
||||||
VP8Histogram* WEBP_RESTRICT const histo) {
|
VP8Histogram* WEBP_RESTRICT const histo) {
|
||||||
int j;
|
int j;
|
||||||
int distribution[MAX_COEFF_THRESH + 1] = { 0 };
|
int distribution[MAX_COEFF_THRESH + 1] = {0};
|
||||||
for (j = start_block; j < end_block; ++j) {
|
for (j = start_block; j < end_block; ++j) {
|
||||||
int k;
|
int k;
|
||||||
int16_t out[16];
|
int16_t out[16];
|
||||||
@@ -105,7 +103,6 @@ static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Transforms (Paragraph 14.4)
|
// Transforms (Paragraph 14.4)
|
||||||
|
|
||||||
@@ -154,8 +151,7 @@ static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
|
|
||||||
static void ITransform_C(const uint8_t* WEBP_RESTRICT ref,
|
static void ITransform_C(const uint8_t* WEBP_RESTRICT ref,
|
||||||
const int16_t* WEBP_RESTRICT in,
|
const int16_t* WEBP_RESTRICT in,
|
||||||
uint8_t* WEBP_RESTRICT dst,
|
uint8_t* WEBP_RESTRICT dst, int do_two) {
|
||||||
int do_two) {
|
|
||||||
ITransformOne(ref, in, dst);
|
ITransformOne(ref, in, dst);
|
||||||
if (do_two) {
|
if (do_two) {
|
||||||
ITransformOne(ref + 4, in + 16, dst + 4);
|
ITransformOne(ref + 4, in + 16, dst + 4);
|
||||||
@@ -183,13 +179,13 @@ static void FTransform_C(const uint8_t* WEBP_RESTRICT src,
|
|||||||
}
|
}
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b
|
const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b
|
||||||
const int a1 = (tmp[4 + i] + tmp[ 8 + i]);
|
const int a1 = (tmp[4 + i] + tmp[8 + i]);
|
||||||
const int a2 = (tmp[4 + i] - tmp[ 8 + i]);
|
const int a2 = (tmp[4 + i] - tmp[8 + i]);
|
||||||
const int a3 = (tmp[0 + i] - tmp[12 + i]);
|
const int a3 = (tmp[0 + i] - tmp[12 + i]);
|
||||||
out[0 + i] = (a0 + a1 + 7) >> 4; // 12b
|
out[0 + i] = (a0 + a1 + 7) >> 4; // 12b
|
||||||
out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0);
|
out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0);
|
||||||
out[8 + i] = (a0 - a1 + 7) >> 4;
|
out[8 + i] = (a0 - a1 + 7) >> 4;
|
||||||
out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16);
|
out[12 + i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !WEBP_NEON_OMIT_C_CODE
|
#endif // !WEBP_NEON_OMIT_C_CODE
|
||||||
@@ -219,16 +215,16 @@ static void FTransformWHT_C(const int16_t* WEBP_RESTRICT in,
|
|||||||
}
|
}
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b
|
const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b
|
||||||
const int a1 = (tmp[4 + i] + tmp[12+ i]);
|
const int a1 = (tmp[4 + i] + tmp[12 + i]);
|
||||||
const int a2 = (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 a3 = (tmp[0 + i] - tmp[8 + i]);
|
||||||
const int b0 = a0 + a1; // 16b
|
const int b0 = a0 + a1; // 16b
|
||||||
const int b1 = a3 + a2;
|
const int b1 = a3 + a2;
|
||||||
const int b2 = a3 - a2;
|
const int b2 = a3 - a2;
|
||||||
const int b3 = a0 - a1;
|
const int b3 = a0 - a1;
|
||||||
out[ 0 + i] = b0 >> 1; // 15b
|
out[0 + i] = b0 >> 1; // 15b
|
||||||
out[ 4 + i] = b1 >> 1;
|
out[4 + i] = b1 >> 1;
|
||||||
out[ 8 + i] = b2 >> 1;
|
out[8 + i] = b2 >> 1;
|
||||||
out[12 + i] = b3 >> 1;
|
out[12 + i] = b3 >> 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,8 +299,8 @@ static WEBP_INLINE void TrueMotion(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
static WEBP_INLINE void DCMode(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void DCMode(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT left,
|
const uint8_t* WEBP_RESTRICT left,
|
||||||
const uint8_t* WEBP_RESTRICT top,
|
const uint8_t* WEBP_RESTRICT top, int size,
|
||||||
int size, int round, int shift) {
|
int round, int shift) {
|
||||||
int DC = 0;
|
int DC = 0;
|
||||||
int j;
|
int j;
|
||||||
if (top != NULL) {
|
if (top != NULL) {
|
||||||
@@ -373,9 +369,9 @@ static void Intra16Preds_C(uint8_t* WEBP_RESTRICT dst,
|
|||||||
static void VE4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void VE4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
const uint8_t vals[4] = {
|
const uint8_t vals[4] = {
|
||||||
AVG3(top[-1], top[0], top[1]),
|
AVG3(top[-1], top[0], top[1]),
|
||||||
AVG3(top[ 0], top[1], top[2]),
|
AVG3(top[0], top[1], top[2]),
|
||||||
AVG3(top[ 1], top[2], top[3]),
|
AVG3(top[1], top[2], top[3]),
|
||||||
AVG3(top[ 2], top[3], top[4])
|
AVG3(top[2], top[3], top[4]),
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
@@ -495,8 +491,7 @@ static void HU4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
|||||||
DST(1, 0) = AVG3(I, J, K);
|
DST(1, 0) = AVG3(I, J, K);
|
||||||
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
||||||
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
||||||
DST(3, 2) = DST(2, 2) =
|
DST(3, 2) = DST(2, 2) = DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
||||||
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void HD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
@@ -561,8 +556,7 @@ static void Intra4Preds_C(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
static WEBP_INLINE int GetSSE(const uint8_t* WEBP_RESTRICT a,
|
static WEBP_INLINE int GetSSE(const uint8_t* WEBP_RESTRICT a,
|
||||||
const uint8_t* WEBP_RESTRICT b,
|
const uint8_t* WEBP_RESTRICT b, int w, int h) {
|
||||||
int w, int h) {
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int y, x;
|
int y, x;
|
||||||
for (y = 0; y < h; ++y) {
|
for (y = 0; y < h; ++y) {
|
||||||
@@ -637,17 +631,17 @@ static int TTransform(const uint8_t* WEBP_RESTRICT in,
|
|||||||
// vertical pass
|
// vertical pass
|
||||||
for (i = 0; i < 4; ++i, ++w) {
|
for (i = 0; i < 4; ++i, ++w) {
|
||||||
const int a0 = tmp[0 + i] + tmp[8 + i];
|
const int a0 = tmp[0 + i] + tmp[8 + i];
|
||||||
const int a1 = tmp[4 + i] + tmp[12+ i];
|
const int a1 = tmp[4 + i] + tmp[12 + i];
|
||||||
const int a2 = 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 a3 = tmp[0 + i] - tmp[8 + i];
|
||||||
const int b0 = a0 + a1;
|
const int b0 = a0 + a1;
|
||||||
const int b1 = a3 + a2;
|
const int b1 = a3 + a2;
|
||||||
const int b2 = a3 - a2;
|
const int b2 = a3 - a2;
|
||||||
const int b3 = a0 - a1;
|
const int b3 = a0 - a1;
|
||||||
|
|
||||||
sum += w[ 0] * abs(b0);
|
sum += w[0] * abs(b0);
|
||||||
sum += w[ 4] * abs(b1);
|
sum += w[4] * abs(b1);
|
||||||
sum += w[ 8] * abs(b2);
|
sum += w[8] * abs(b2);
|
||||||
sum += w[12] * abs(b3);
|
sum += w[12] * abs(b3);
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
@@ -680,9 +674,8 @@ static int Disto16x16_C(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
//
|
//
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
|
||||||
static const uint8_t kZigzag[16] = {
|
static const uint8_t kZigzag[16] = {0, 1, 4, 8, 5, 2, 3, 6,
|
||||||
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
|
9, 12, 13, 10, 7, 11, 14, 15};
|
||||||
};
|
|
||||||
|
|
||||||
// Simple quantization
|
// Simple quantization
|
||||||
static int QuantizeBlock_C(int16_t in[16], int16_t out[16],
|
static int QuantizeBlock_C(int16_t in[16], int16_t out[16],
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#if defined(WEBP_USE_MIPS32)
|
#if defined(WEBP_USE_MIPS32)
|
||||||
|
|
||||||
#include "src/dsp/mips_macro.h"
|
#include "src/dsp/mips_macro.h"
|
||||||
#include "src/enc/vp8i_enc.h"
|
|
||||||
#include "src/enc/cost_enc.h"
|
#include "src/enc/cost_enc.h"
|
||||||
|
#include "src/enc/vp8i_enc.h"
|
||||||
|
|
||||||
static const int kC1 = WEBP_TRANSFORM_AC3_C1;
|
static const int kC1 = WEBP_TRANSFORM_AC3_C1;
|
||||||
static const int kC2 = WEBP_TRANSFORM_AC3_C2;
|
static const int kC2 = WEBP_TRANSFORM_AC3_C2;
|
||||||
@@ -30,6 +30,7 @@ static const int kC2 = WEBP_TRANSFORM_AC3_C2;
|
|||||||
// A..D - offsets in bytes to load from in buffer
|
// A..D - offsets in bytes to load from in buffer
|
||||||
// TEMP0..TEMP3 - registers for corresponding tmp elements
|
// TEMP0..TEMP3 - registers for corresponding tmp elements
|
||||||
// TEMP4..TEMP5 - temporary registers
|
// TEMP4..TEMP5 - temporary registers
|
||||||
|
// clang-format off
|
||||||
#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \
|
#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \
|
||||||
"lh %[temp16], " #A "(%[temp20]) \n\t" \
|
"lh %[temp16], " #A "(%[temp20]) \n\t" \
|
||||||
"lh %[temp18], " #B "(%[temp20]) \n\t" \
|
"lh %[temp18], " #B "(%[temp20]) \n\t" \
|
||||||
@@ -107,6 +108,7 @@ static const int kC2 = WEBP_TRANSFORM_AC3_C2;
|
|||||||
"sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
|
"sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
|
||||||
"sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
|
"sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
|
||||||
"sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t"
|
"sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
// Does one or two inverse transforms.
|
// Does one or two inverse transforms.
|
||||||
static WEBP_INLINE void ITransformOne_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
static WEBP_INLINE void ITransformOne_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
||||||
@@ -118,27 +120,26 @@ static WEBP_INLINE void ITransformOne_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst};
|
const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst};
|
||||||
|
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
"lw %[temp20], 4(%[args]) \n\t"
|
"lw %[temp20], 4(%[args]) \n\t" //
|
||||||
VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3)
|
VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3) //
|
||||||
VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7)
|
VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7) //
|
||||||
VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11)
|
VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11) //
|
||||||
VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15)
|
VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15) //
|
||||||
|
|
||||||
HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12)
|
HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12) //
|
||||||
HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13)
|
HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13) //
|
||||||
HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14)
|
HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14) //
|
||||||
HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15)
|
HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15) //
|
||||||
|
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [temp8] "=&r"(temp8),
|
||||||
[temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
|
[temp9] "=&r"(temp9), [temp10] "=&r"(temp10), [temp11] "=&r"(temp11),
|
||||||
[temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
|
[temp12] "=&r"(temp12), [temp13] "=&r"(temp13), [temp14] "=&r"(temp14),
|
||||||
[temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
|
[temp15] "=&r"(temp15), [temp16] "=&r"(temp16), [temp17] "=&r"(temp17),
|
||||||
[temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
|
[temp18] "=&r"(temp18), [temp19] "=&r"(temp19), [temp20] "=&r"(temp20)
|
||||||
: [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2)
|
: [args] "r"(args), [kC1] "r"(kC1), [kC2] "r"(kC2)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ITransform_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
static void ITransform_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
||||||
@@ -158,6 +159,7 @@ static void ITransform_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
// J - offset in bytes (kZigzag[n] * 2)
|
// J - offset in bytes (kZigzag[n] * 2)
|
||||||
// K - offset in bytes (kZigzag[n] * 4)
|
// K - offset in bytes (kZigzag[n] * 4)
|
||||||
// N - offset in bytes (n * 2)
|
// N - offset in bytes (n * 2)
|
||||||
|
// clang-format off
|
||||||
#define QUANTIZE_ONE(J, K, N) \
|
#define QUANTIZE_ONE(J, K, N) \
|
||||||
"lh %[temp0], " #J "(%[ppin]) \n\t" \
|
"lh %[temp0], " #J "(%[ppin]) \n\t" \
|
||||||
"lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \
|
"lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \
|
||||||
@@ -184,6 +186,7 @@ static void ITransform_MIPS32(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
"2: \n\t" \
|
"2: \n\t" \
|
||||||
"sh %[temp5], " #J "(%[ppin]) \n\t" \
|
"sh %[temp5], " #J "(%[ppin]) \n\t" \
|
||||||
"sh %[level], " #N "(%[pout]) \n\t"
|
"sh %[level], " #N "(%[pout]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static int QuantizeBlock_MIPS32(int16_t in[16], int16_t out[16],
|
static int QuantizeBlock_MIPS32(int16_t in[16], int16_t out[16],
|
||||||
const VP8Matrix* const mtx) {
|
const VP8Matrix* const mtx) {
|
||||||
@@ -200,34 +203,30 @@ static int QuantizeBlock_MIPS32(int16_t in[16], int16_t out[16],
|
|||||||
const uint32_t* ppbias = &mtx->bias[0];
|
const uint32_t* ppbias = &mtx->bias[0];
|
||||||
|
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
QUANTIZE_ONE( 0, 0, 0)
|
QUANTIZE_ONE(0, 0, 0) //
|
||||||
QUANTIZE_ONE( 2, 4, 2)
|
QUANTIZE_ONE(2, 4, 2) //
|
||||||
QUANTIZE_ONE( 8, 16, 4)
|
QUANTIZE_ONE(8, 16, 4) //
|
||||||
QUANTIZE_ONE(16, 32, 6)
|
QUANTIZE_ONE(16, 32, 6) //
|
||||||
QUANTIZE_ONE(10, 20, 8)
|
QUANTIZE_ONE(10, 20, 8) //
|
||||||
QUANTIZE_ONE( 4, 8, 10)
|
QUANTIZE_ONE(4, 8, 10) //
|
||||||
QUANTIZE_ONE( 6, 12, 12)
|
QUANTIZE_ONE(6, 12, 12) //
|
||||||
QUANTIZE_ONE(12, 24, 14)
|
QUANTIZE_ONE(12, 24, 14) //
|
||||||
QUANTIZE_ONE(18, 36, 16)
|
QUANTIZE_ONE(18, 36, 16) //
|
||||||
QUANTIZE_ONE(24, 48, 18)
|
QUANTIZE_ONE(24, 48, 18) //
|
||||||
QUANTIZE_ONE(26, 52, 20)
|
QUANTIZE_ONE(26, 52, 20) //
|
||||||
QUANTIZE_ONE(20, 40, 22)
|
QUANTIZE_ONE(20, 40, 22) //
|
||||||
QUANTIZE_ONE(14, 28, 24)
|
QUANTIZE_ONE(14, 28, 24) //
|
||||||
QUANTIZE_ONE(22, 44, 26)
|
QUANTIZE_ONE(22, 44, 26) //
|
||||||
QUANTIZE_ONE(28, 56, 28)
|
QUANTIZE_ONE(28, 56, 28) //
|
||||||
QUANTIZE_ONE(30, 60, 30)
|
QUANTIZE_ONE(30, 60, 30) //
|
||||||
|
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[sign] "=&r"(sign), [coeff] "=&r"(coeff), [level] "=&r"(level)
|
||||||
[sign]"=&r"(sign), [coeff]"=&r"(coeff),
|
: [pout] "r"(pout), [ppin] "r"(ppin), [ppiq] "r"(ppiq),
|
||||||
[level]"=&r"(level)
|
[max_level] "r"(max_level), [ppbias] "r"(ppbias),
|
||||||
: [pout]"r"(pout), [ppin]"r"(ppin),
|
[ppzthresh] "r"(ppzthresh), [ppsharpen] "r"(ppsharpen), [ppq] "r"(ppq)
|
||||||
[ppiq]"r"(ppiq), [max_level]"r"(max_level),
|
: "memory", "hi", "lo");
|
||||||
[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
|
// moved out from macro to increase possibility for earlier breaking
|
||||||
for (i = 15; i >= 0; i--) {
|
for (i = 15; i >= 0; i--) {
|
||||||
@@ -251,6 +250,7 @@ static int Quantize2Blocks_MIPS32(int16_t in[32], int16_t out[32],
|
|||||||
// A - offset in bytes to load from a and b buffers
|
// A - offset in bytes to load from a and b buffers
|
||||||
// E..H - offsets in bytes to store first results to tmp buffer
|
// E..H - offsets in bytes to store first results to tmp buffer
|
||||||
// E1..H1 - offsets in bytes to store second results to tmp buffer
|
// E1..H1 - offsets in bytes to store second results to tmp buffer
|
||||||
|
// clang-format off
|
||||||
#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \
|
#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \
|
||||||
"lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
|
"lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
|
||||||
"lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
|
"lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
|
||||||
@@ -358,6 +358,7 @@ static int Quantize2Blocks_MIPS32(int16_t in[32], int16_t out[32],
|
|||||||
"msub %[temp5], %[temp8] \n\t" \
|
"msub %[temp5], %[temp8] \n\t" \
|
||||||
"msub %[temp6], %[temp0] \n\t" \
|
"msub %[temp6], %[temp0] \n\t" \
|
||||||
"msub %[temp7], %[temp1] \n\t"
|
"msub %[temp7], %[temp1] \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static int Disto4x4_MIPS32(const uint8_t* WEBP_RESTRICT const a,
|
static int Disto4x4_MIPS32(const uint8_t* WEBP_RESTRICT const a,
|
||||||
const uint8_t* WEBP_RESTRICT const b,
|
const uint8_t* WEBP_RESTRICT const b,
|
||||||
@@ -366,28 +367,27 @@ static int Disto4x4_MIPS32(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
||||||
|
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76)
|
HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76) //
|
||||||
HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92)
|
HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92) //
|
||||||
HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108)
|
HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108) //
|
||||||
HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124)
|
HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124) //
|
||||||
"mthi $zero \n\t"
|
"mthi $zero \n\t"
|
||||||
"mtlo $zero \n\t"
|
"mtlo $zero \n\t" //
|
||||||
VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24)
|
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(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(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)
|
VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30) //
|
||||||
"mflo %[temp0] \n\t"
|
"mflo %[temp0] \n\t"
|
||||||
"sra %[temp1], %[temp0], 31 \n\t"
|
"sra %[temp1], %[temp0], 31 \n\t"
|
||||||
"xor %[temp0], %[temp0], %[temp1] \n\t"
|
"xor %[temp0], %[temp0], %[temp1] \n\t"
|
||||||
"subu %[temp0], %[temp0], %[temp1] \n\t"
|
"subu %[temp0], %[temp0], %[temp1] \n\t"
|
||||||
"sra %[temp0], %[temp0], 5 \n\t"
|
"sra %[temp0], %[temp0], 5 \n\t"
|
||||||
|
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [temp8] "=&r"(temp8)
|
||||||
: [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp)
|
: [a] "r"(a), [b] "r"(b), [w] "r"(w), [tmp] "r"(tmp)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
|
|
||||||
return temp0;
|
return temp0;
|
||||||
}
|
}
|
||||||
@@ -412,6 +412,7 @@ static int Disto16x16_MIPS32(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
// temp0..temp15 holds tmp[0]..tmp[15]
|
// temp0..temp15 holds tmp[0]..tmp[15]
|
||||||
// A - offset in bytes to load from src and ref buffers
|
// A - offset in bytes to load from src and ref buffers
|
||||||
// TEMP0..TEMP3 - registers for corresponding tmp elements
|
// TEMP0..TEMP3 - registers for corresponding tmp elements
|
||||||
|
// clang-format off
|
||||||
#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \
|
#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \
|
||||||
"lw %[" #TEMP1 "], 0(%[args]) \n\t" \
|
"lw %[" #TEMP1 "], 0(%[args]) \n\t" \
|
||||||
"lw %[" #TEMP2 "], 4(%[args]) \n\t" \
|
"lw %[" #TEMP2 "], 4(%[args]) \n\t" \
|
||||||
@@ -477,6 +478,7 @@ static int Disto16x16_MIPS32(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
"sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
|
"sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
|
||||||
"sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
|
"sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
|
||||||
"sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
|
"sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void FTransform_MIPS32(const uint8_t* WEBP_RESTRICT src,
|
static void FTransform_MIPS32(const uint8_t* WEBP_RESTRICT src,
|
||||||
const uint8_t* WEBP_RESTRICT ref,
|
const uint8_t* WEBP_RESTRICT ref,
|
||||||
@@ -486,8 +488,8 @@ static void FTransform_MIPS32(const uint8_t* WEBP_RESTRICT src,
|
|||||||
int temp17, temp18, temp19, temp20;
|
int temp17, temp18, temp19, temp20;
|
||||||
const int c2217 = 2217;
|
const int c2217 = 2217;
|
||||||
const int c5352 = 5352;
|
const int c5352 = 5352;
|
||||||
const int* const args[3] =
|
const int* const args[3] = {(const int*)src, (const int*)ref,
|
||||||
{ (const int*)src, (const int*)ref, (const int*)out };
|
(const int*)out};
|
||||||
|
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
|
HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
|
||||||
@@ -517,6 +519,7 @@ static void FTransform_MIPS32(const uint8_t* WEBP_RESTRICT src,
|
|||||||
|
|
||||||
#if !defined(WORK_AROUND_GCC)
|
#if !defined(WORK_AROUND_GCC)
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define GET_SSE_INNER(A, B, C, D) \
|
#define GET_SSE_INNER(A, B, C, D) \
|
||||||
"lbu %[temp0], " #A "(%[a]) \n\t" \
|
"lbu %[temp0], " #A "(%[a]) \n\t" \
|
||||||
"lbu %[temp1], " #A "(%[b]) \n\t" \
|
"lbu %[temp1], " #A "(%[b]) \n\t" \
|
||||||
@@ -534,6 +537,7 @@ static void FTransform_MIPS32(const uint8_t* WEBP_RESTRICT src,
|
|||||||
"madd %[temp2], %[temp2] \n\t" \
|
"madd %[temp2], %[temp2] \n\t" \
|
||||||
"madd %[temp4], %[temp4] \n\t" \
|
"madd %[temp4], %[temp4] \n\t" \
|
||||||
"madd %[temp6], %[temp6] \n\t"
|
"madd %[temp6], %[temp6] \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#define GET_SSE(A, B, C, D) \
|
#define GET_SSE(A, B, C, D) \
|
||||||
GET_SSE_INNER(A, A + 1, A + 2, A + 3) \
|
GET_SSE_INNER(A, A + 1, A + 2, A + 3) \
|
||||||
@@ -549,30 +553,29 @@ static int SSE16x16_MIPS32(const uint8_t* WEBP_RESTRICT a,
|
|||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t"
|
||||||
|
|
||||||
GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
|
GET_SSE(0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) //
|
||||||
GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
|
GET_SSE(1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) //
|
||||||
GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
|
GET_SSE(2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) //
|
||||||
GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
|
GET_SSE(3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) //
|
||||||
GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
|
GET_SSE(4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) //
|
||||||
GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
|
GET_SSE(5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) //
|
||||||
GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
|
GET_SSE(6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) //
|
||||||
GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
|
GET_SSE(7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) //
|
||||||
GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS)
|
GET_SSE(8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) //
|
||||||
GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS)
|
GET_SSE(9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) //
|
||||||
GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS)
|
GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) //
|
||||||
GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS)
|
GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) //
|
||||||
GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS)
|
GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) //
|
||||||
GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS)
|
GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) //
|
||||||
GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS)
|
GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) //
|
||||||
GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS)
|
GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) //
|
||||||
|
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,22 +587,21 @@ static int SSE16x8_MIPS32(const uint8_t* WEBP_RESTRICT a,
|
|||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t"
|
||||||
|
|
||||||
GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
|
GET_SSE(0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) //
|
||||||
GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
|
GET_SSE(1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) //
|
||||||
GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
|
GET_SSE(2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) //
|
||||||
GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
|
GET_SSE(3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) //
|
||||||
GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
|
GET_SSE(4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) //
|
||||||
GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
|
GET_SSE(5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) //
|
||||||
GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
|
GET_SSE(6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) //
|
||||||
GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
|
GET_SSE(7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) //
|
||||||
|
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,18 +613,17 @@ static int SSE8x8_MIPS32(const uint8_t* WEBP_RESTRICT a,
|
|||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t"
|
||||||
|
|
||||||
GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS)
|
GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) //
|
||||||
GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS)
|
GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) //
|
||||||
GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS)
|
GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) //
|
||||||
GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS)
|
GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) //
|
||||||
|
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,15 +635,14 @@ static int SSE4x4_MIPS32(const uint8_t* WEBP_RESTRICT a,
|
|||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t"
|
||||||
|
|
||||||
GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS)
|
GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) //
|
||||||
|
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ static const int kC2 = WEBP_TRANSFORM_AC3_C2;
|
|||||||
|
|
||||||
// O - output
|
// O - output
|
||||||
// I - input (macro doesn't change it)
|
// I - input (macro doesn't change it)
|
||||||
|
// clang-format off
|
||||||
#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \
|
#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \
|
||||||
I0, I1, I2, I3, I4, I5, I6, I7) \
|
I0, I1, I2, I3, I4, I5, I6, I7) \
|
||||||
"addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \
|
"addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \
|
||||||
@@ -140,6 +141,7 @@ static const int kC2 = WEBP_TRANSFORM_AC3_C2;
|
|||||||
"sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
|
"sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
|
||||||
"sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
|
"sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
|
||||||
"sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
|
"sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void FTransform_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
static void FTransform_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
||||||
const uint8_t* WEBP_RESTRICT ref,
|
const uint8_t* WEBP_RESTRICT ref,
|
||||||
@@ -149,10 +151,10 @@ static void FTransform_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
|||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
||||||
int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
|
int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
|
||||||
int temp17, temp18, temp19, temp20;
|
int temp17, temp18, temp19, temp20;
|
||||||
const int* const args[3] =
|
const int* const args[3] = {(const int*)src, (const int*)ref,
|
||||||
{ (const int*)src, (const int*)ref, (const int*)out };
|
(const int*)out};
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
|
HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
|
||||||
HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7)
|
HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7)
|
||||||
HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11)
|
HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11)
|
||||||
@@ -178,7 +180,7 @@ static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
||||||
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
|
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp1], 0(%[in]) \n\t"
|
"ulw %[temp1], 0(%[in]) \n\t"
|
||||||
"ulw %[temp2], 16(%[in]) \n\t"
|
"ulw %[temp2], 16(%[in]) \n\t"
|
||||||
LOAD_IN_X2(temp5, temp6, 24, 26)
|
LOAD_IN_X2(temp5, temp6, 24, 26)
|
||||||
@@ -250,13 +252,14 @@ static void ITransform_MIPSdspR2(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
static int Disto4x4_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
static int Disto4x4_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
||||||
const uint8_t* WEBP_RESTRICT const b,
|
const uint8_t* WEBP_RESTRICT const b,
|
||||||
const uint16_t* WEBP_RESTRICT const w) {
|
const uint16_t* WEBP_RESTRICT const w) {
|
||||||
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
|
||||||
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17;
|
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a,
|
LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 1, 2, 3,
|
0, 1, 2, 3,
|
||||||
@@ -317,6 +320,7 @@ static int Disto4x4_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
);
|
);
|
||||||
return abs(temp3 - temp17) >> 5;
|
return abs(temp3 - temp17) >> 5;
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static int Disto16x16_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
static int Disto16x16_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
||||||
const uint8_t* WEBP_RESTRICT const b,
|
const uint8_t* WEBP_RESTRICT const b,
|
||||||
@@ -334,6 +338,7 @@ static int Disto16x16_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Intra predictions
|
// Intra predictions
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define FILL_PART(J, SIZE) \
|
#define FILL_PART(J, SIZE) \
|
||||||
"usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
|
"usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
|
||||||
"usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
|
"usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
|
||||||
@@ -342,9 +347,10 @@ static int Disto16x16_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
"usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
|
"usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
|
||||||
".endif \n\t"
|
".endif \n\t"
|
||||||
|
|
||||||
#define FILL_8_OR_16(DST, VALUE, SIZE) do { \
|
#define FILL_8_OR_16(DST, VALUE, SIZE) \
|
||||||
|
do { \
|
||||||
int value = (VALUE); \
|
int value = (VALUE); \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile( \
|
||||||
"replv.qb %[value], %[value] \n\t" \
|
"replv.qb %[value], %[value] \n\t" \
|
||||||
FILL_PART( 0, SIZE) \
|
FILL_PART( 0, SIZE) \
|
||||||
FILL_PART( 1, SIZE) \
|
FILL_PART( 1, SIZE) \
|
||||||
@@ -368,18 +374,19 @@ static int Disto16x16_MIPSdspR2(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
: [dst]"r"((DST)) \
|
: [dst]"r"((DST)) \
|
||||||
: "memory" \
|
: "memory" \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#define VERTICAL_PRED(DST, TOP, SIZE) \
|
#define VERTICAL_PRED(DST, TOP, SIZE) \
|
||||||
static WEBP_INLINE void VerticalPred##SIZE( \
|
static WEBP_INLINE void VerticalPred##SIZE( \
|
||||||
uint8_t* WEBP_RESTRICT (DST), const uint8_t* WEBP_RESTRICT (TOP)) { \
|
uint8_t* WEBP_RESTRICT(DST), const uint8_t* WEBP_RESTRICT(TOP)) { \
|
||||||
int j; \
|
int j; \
|
||||||
if ((TOP)) { \
|
if ((TOP)) { \
|
||||||
for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \
|
for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \
|
||||||
} else { \
|
} else { \
|
||||||
FILL_8_OR_16((DST), 127, (SIZE)); \
|
FILL_8_OR_16((DST), 127, (SIZE)); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
VERTICAL_PRED(dst, top, 8)
|
VERTICAL_PRED(dst, top, 8)
|
||||||
VERTICAL_PRED(dst, top, 16)
|
VERTICAL_PRED(dst, top, 16)
|
||||||
@@ -387,8 +394,8 @@ VERTICAL_PRED(dst, top, 16)
|
|||||||
#undef VERTICAL_PRED
|
#undef VERTICAL_PRED
|
||||||
|
|
||||||
#define HORIZONTAL_PRED(DST, LEFT, SIZE) \
|
#define HORIZONTAL_PRED(DST, LEFT, SIZE) \
|
||||||
static WEBP_INLINE void HorizontalPred##SIZE( \
|
static WEBP_INLINE void HorizontalPred##SIZE( \
|
||||||
uint8_t* WEBP_RESTRICT (DST), const uint8_t* WEBP_RESTRICT (LEFT)) { \
|
uint8_t* WEBP_RESTRICT(DST), const uint8_t* WEBP_RESTRICT(LEFT)) { \
|
||||||
if (LEFT) { \
|
if (LEFT) { \
|
||||||
int j; \
|
int j; \
|
||||||
for (j = 0; j < (SIZE); ++j) { \
|
for (j = 0; j < (SIZE); ++j) { \
|
||||||
@@ -397,7 +404,7 @@ static WEBP_INLINE void HorizontalPred##SIZE( \
|
|||||||
} else { \
|
} else { \
|
||||||
FILL_8_OR_16((DST), 129, (SIZE)); \
|
FILL_8_OR_16((DST), 129, (SIZE)); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
HORIZONTAL_PRED(dst, left, 8)
|
HORIZONTAL_PRED(dst, left, 8)
|
||||||
HORIZONTAL_PRED(dst, left, 16)
|
HORIZONTAL_PRED(dst, left, 16)
|
||||||
@@ -420,10 +427,12 @@ HORIZONTAL_PRED(dst, left, 16)
|
|||||||
"precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \
|
"precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \
|
||||||
"precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
|
"precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
|
||||||
|
|
||||||
#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \
|
// clang-format off
|
||||||
|
#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) \
|
||||||
|
do { \
|
||||||
int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \
|
int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \
|
||||||
int temp0, temp1, temp2, temp3; \
|
int temp0, temp1, temp2, temp3; \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile( \
|
||||||
"replv.ph %[leftY_1], %[leftY_1] \n\t" \
|
"replv.ph %[leftY_1], %[leftY_1] \n\t" \
|
||||||
"ulw %[temp0], 0(%[top]) \n\t" \
|
"ulw %[temp0], 0(%[top]) \n\t" \
|
||||||
"ulw %[temp1], 4(%[top]) \n\t" \
|
"ulw %[temp1], 4(%[top]) \n\t" \
|
||||||
@@ -443,17 +452,20 @@ HORIZONTAL_PRED(dst, left, 16)
|
|||||||
: [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \
|
: [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \
|
||||||
: "memory" \
|
: "memory" \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \
|
#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) \
|
||||||
|
do { \
|
||||||
int y; \
|
int y; \
|
||||||
const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \
|
const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \
|
||||||
for (y = 0; y < (SIZE); ++y) { \
|
for (y = 0; y < (SIZE); ++y) { \
|
||||||
CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \
|
CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \
|
||||||
(DST) += BPS; \
|
(DST) += BPS; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \
|
#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \
|
||||||
static WEBP_INLINE void TrueMotion##SIZE(uint8_t* WEBP_RESTRICT (DST), \
|
static WEBP_INLINE void TrueMotion##SIZE(uint8_t* WEBP_RESTRICT (DST), \
|
||||||
const uint8_t* WEBP_RESTRICT (LEFT), \
|
const uint8_t* WEBP_RESTRICT (LEFT), \
|
||||||
@@ -476,6 +488,7 @@ static WEBP_INLINE void TrueMotion##SIZE(uint8_t* WEBP_RESTRICT (DST), \
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
TRUE_MOTION(dst, left, top, 8)
|
TRUE_MOTION(dst, left, top, 8)
|
||||||
TRUE_MOTION(dst, left, top, 16)
|
TRUE_MOTION(dst, left, top, 16)
|
||||||
@@ -586,11 +599,10 @@ static WEBP_INLINE void DCMode8(uint8_t* WEBP_RESTRICT dst,
|
|||||||
"4: \n\t"
|
"4: \n\t"
|
||||||
"li %[DC], 0x80 \n\t"
|
"li %[DC], 0x80 \n\t"
|
||||||
"5: \n\t"
|
"5: \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [DC] "=&r"(DC),
|
||||||
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1)
|
[temp2] "=&r"(temp2), [temp3] "=&r"(temp3), [DC1] "=&r"(DC1)
|
||||||
: [left]"r"(left), [top]"r"(top)
|
: [left] "r"(left), [top] "r"(top)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
|
|
||||||
FILL_8_OR_16(dst, DC, 8);
|
FILL_8_OR_16(dst, DC, 8);
|
||||||
}
|
}
|
||||||
@@ -619,7 +631,7 @@ static void DC4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
|||||||
static void TM4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void TM4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5;
|
int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5;
|
||||||
const int c35 = 0xff00ff;
|
const int c35 = 0xff00ff;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"lbu %[temp1], 0(%[top]) \n\t"
|
"lbu %[temp1], 0(%[top]) \n\t"
|
||||||
"lbu %[a10], 1(%[top]) \n\t"
|
"lbu %[a10], 1(%[top]) \n\t"
|
||||||
"lbu %[temp2], 2(%[top]) \n\t"
|
"lbu %[temp2], 2(%[top]) \n\t"
|
||||||
@@ -790,7 +802,7 @@ static void RD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
|||||||
static void VR4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void VR4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8, temp9;
|
int temp5, temp6, temp7, temp8, temp9;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], -4(%[top]) \n\t"
|
"ulw %[temp0], -4(%[top]) \n\t"
|
||||||
"ulw %[temp1], 0(%[top]) \n\t"
|
"ulw %[temp1], 0(%[top]) \n\t"
|
||||||
"preceu.ph.qbl %[temp2], %[temp0] \n\t"
|
"preceu.ph.qbl %[temp2], %[temp0] \n\t"
|
||||||
@@ -887,7 +899,7 @@ static void LD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
|||||||
static void VL4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void VL4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8, temp9;
|
int temp5, temp6, temp7, temp8, temp9;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], 0(%[top]) \n\t"
|
"ulw %[temp0], 0(%[top]) \n\t"
|
||||||
"ulw %[temp1], 4(%[top]) \n\t"
|
"ulw %[temp1], 4(%[top]) \n\t"
|
||||||
"preceu.ph.qbla %[temp2], %[temp0] \n\t"
|
"preceu.ph.qbla %[temp2], %[temp0] \n\t"
|
||||||
@@ -936,7 +948,7 @@ static void VL4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
|||||||
static void HD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void HD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8, temp9;
|
int temp5, temp6, temp7, temp8, temp9;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], -5(%[top]) \n\t"
|
"ulw %[temp0], -5(%[top]) \n\t"
|
||||||
"ulw %[temp1], -1(%[top]) \n\t"
|
"ulw %[temp1], -1(%[top]) \n\t"
|
||||||
"preceu.ph.qbla %[temp2], %[temp0] \n\t"
|
"preceu.ph.qbla %[temp2], %[temp0] \n\t"
|
||||||
@@ -983,7 +995,7 @@ static void HD4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
|||||||
|
|
||||||
static void HU4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
static void HU4(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT top) {
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"ulw %[temp0], -5(%[top]) \n\t"
|
"ulw %[temp0], -5(%[top]) \n\t"
|
||||||
"preceu.ph.qbl %[temp1], %[temp0] \n\t"
|
"preceu.ph.qbl %[temp1], %[temp0] \n\t"
|
||||||
"preceu.ph.qbr %[temp2], %[temp0] \n\t"
|
"preceu.ph.qbr %[temp2], %[temp0] \n\t"
|
||||||
@@ -1071,6 +1083,7 @@ static void Intra4Preds_MIPSdspR2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
#if !defined(WORK_AROUND_GCC)
|
#if !defined(WORK_AROUND_GCC)
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define GET_SSE_INNER(A) \
|
#define GET_SSE_INNER(A) \
|
||||||
"lw %[temp0], " #A "(%[a]) \n\t" \
|
"lw %[temp0], " #A "(%[a]) \n\t" \
|
||||||
"lw %[temp1], " #A "(%[b]) \n\t" \
|
"lw %[temp1], " #A "(%[b]) \n\t" \
|
||||||
@@ -1082,6 +1095,7 @@ static void Intra4Preds_MIPSdspR2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
"subq.ph %[temp0], %[temp0], %[temp1] \n\t" \
|
"subq.ph %[temp0], %[temp0], %[temp1] \n\t" \
|
||||||
"dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \
|
"dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \
|
||||||
"dpa.w.ph $ac0, %[temp0], %[temp0] \n\t"
|
"dpa.w.ph $ac0, %[temp0], %[temp0] \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#define GET_SSE(A, B, C, D) \
|
#define GET_SSE(A, B, C, D) \
|
||||||
GET_SSE_INNER(A) \
|
GET_SSE_INNER(A) \
|
||||||
@@ -1093,30 +1107,29 @@ static int SSE16x16_MIPSdspR2(const uint8_t* WEBP_RESTRICT a,
|
|||||||
const uint8_t* WEBP_RESTRICT b) {
|
const uint8_t* WEBP_RESTRICT b) {
|
||||||
int count;
|
int count;
|
||||||
int temp0, temp1, temp2, temp3;
|
int temp0, temp1, temp2, temp3;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t" //
|
||||||
GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
|
GET_SSE(0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) //
|
||||||
GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
|
GET_SSE(1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) //
|
||||||
GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
|
GET_SSE(2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) //
|
||||||
GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
|
GET_SSE(3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) //
|
||||||
GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
|
GET_SSE(4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) //
|
||||||
GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
|
GET_SSE(5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) //
|
||||||
GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
|
GET_SSE(6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) //
|
||||||
GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
|
GET_SSE(7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) //
|
||||||
GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS)
|
GET_SSE(8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) //
|
||||||
GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS)
|
GET_SSE(9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) //
|
||||||
GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS)
|
GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) //
|
||||||
GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS)
|
GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) //
|
||||||
GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS)
|
GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) //
|
||||||
GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS)
|
GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) //
|
||||||
GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS)
|
GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) //
|
||||||
GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS)
|
GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) //
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [count]"=&r"(count)
|
[temp3] "=&r"(temp3), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,22 +1137,21 @@ static int SSE16x8_MIPSdspR2(const uint8_t* WEBP_RESTRICT a,
|
|||||||
const uint8_t* WEBP_RESTRICT b) {
|
const uint8_t* WEBP_RESTRICT b) {
|
||||||
int count;
|
int count;
|
||||||
int temp0, temp1, temp2, temp3;
|
int temp0, temp1, temp2, temp3;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t" //
|
||||||
GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
|
GET_SSE(0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) //
|
||||||
GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
|
GET_SSE(1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) //
|
||||||
GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
|
GET_SSE(2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) //
|
||||||
GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
|
GET_SSE(3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) //
|
||||||
GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
|
GET_SSE(4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) //
|
||||||
GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
|
GET_SSE(5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) //
|
||||||
GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
|
GET_SSE(6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) //
|
||||||
GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
|
GET_SSE(7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) //
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [count]"=&r"(count)
|
[temp3] "=&r"(temp3), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1147,18 +1159,17 @@ static int SSE8x8_MIPSdspR2(const uint8_t* WEBP_RESTRICT a,
|
|||||||
const uint8_t* WEBP_RESTRICT b) {
|
const uint8_t* WEBP_RESTRICT b) {
|
||||||
int count;
|
int count;
|
||||||
int temp0, temp1, temp2, temp3;
|
int temp0, temp1, temp2, temp3;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t" //
|
||||||
GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS)
|
GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) //
|
||||||
GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS)
|
GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) //
|
||||||
GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS)
|
GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) //
|
||||||
GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS)
|
GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) //
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [count]"=&r"(count)
|
[temp3] "=&r"(temp3), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,15 +1177,14 @@ static int SSE4x4_MIPSdspR2(const uint8_t* WEBP_RESTRICT a,
|
|||||||
const uint8_t* WEBP_RESTRICT b) {
|
const uint8_t* WEBP_RESTRICT b) {
|
||||||
int count;
|
int count;
|
||||||
int temp0, temp1, temp2, temp3;
|
int temp0, temp1, temp2, temp3;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"mult $zero, $zero \n\t"
|
"mult $zero, $zero \n\t" //
|
||||||
GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS)
|
GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) //
|
||||||
"mflo %[count] \n\t"
|
"mflo %[count] \n\t"
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [count]"=&r"(count)
|
[temp3] "=&r"(temp3), [count] "=&r"(count)
|
||||||
: [a]"r"(a), [b]"r"(b)
|
: [a] "r"(a), [b] "r"(b)
|
||||||
: "memory", "hi", "lo"
|
: "memory", "hi", "lo");
|
||||||
);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,6 +1210,7 @@ static int SSE4x4_MIPSdspR2(const uint8_t* WEBP_RESTRICT a,
|
|||||||
// K - offset in bytes (kZigzag[n] * 4)
|
// K - offset in bytes (kZigzag[n] * 4)
|
||||||
// N - offset in bytes (n * 2)
|
// N - offset in bytes (n * 2)
|
||||||
// N1 - offset in bytes ((n + 1) * 2)
|
// N1 - offset in bytes ((n + 1) * 2)
|
||||||
|
// clang-format off
|
||||||
#define QUANTIZE_ONE(J, K, N, N1) \
|
#define QUANTIZE_ONE(J, K, N, N1) \
|
||||||
"ulw %[temp1], " #J "(%[ppin]) \n\t" \
|
"ulw %[temp1], " #J "(%[ppin]) \n\t" \
|
||||||
"ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \
|
"ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \
|
||||||
@@ -1285,10 +1296,11 @@ static int SSE4x4_MIPSdspR2(const uint8_t* WEBP_RESTRICT a,
|
|||||||
"sh $0, " #N1 "(%[pout]) \n\t" \
|
"sh $0, " #N1 "(%[pout]) \n\t" \
|
||||||
"usw $0, " #J "(%[ppin]) \n\t" \
|
"usw $0, " #J "(%[ppin]) \n\t" \
|
||||||
"3: \n\t"
|
"3: \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static int QuantizeBlock_MIPSdspR2(int16_t in[16], int16_t out[16],
|
static int QuantizeBlock_MIPSdspR2(int16_t in[16], int16_t out[16],
|
||||||
const VP8Matrix* WEBP_RESTRICT const mtx) {
|
const VP8Matrix* WEBP_RESTRICT const mtx) {
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5,temp6;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
|
||||||
int sign, coeff, level;
|
int sign, coeff, level;
|
||||||
int max_level = MAX_LEVEL;
|
int max_level = MAX_LEVEL;
|
||||||
int max_level1 = max_level << 16 | max_level;
|
int max_level1 = max_level << 16 | max_level;
|
||||||
@@ -1302,27 +1314,24 @@ static int QuantizeBlock_MIPSdspR2(int16_t in[16], int16_t out[16],
|
|||||||
const uint16_t* ppiq = &mtx->iq[0];
|
const uint16_t* ppiq = &mtx->iq[0];
|
||||||
const uint32_t* ppbias = &mtx->bias[0];
|
const uint32_t* ppbias = &mtx->bias[0];
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
QUANTIZE_ONE( 0, 0, 0, 2)
|
QUANTIZE_ONE(0, 0, 0, 2) //
|
||||||
QUANTIZE_ONE( 4, 8, 10, 12)
|
QUANTIZE_ONE(4, 8, 10, 12) //
|
||||||
QUANTIZE_ONE( 8, 16, 4, 8)
|
QUANTIZE_ONE(8, 16, 4, 8) //
|
||||||
QUANTIZE_ONE(12, 24, 14, 24)
|
QUANTIZE_ONE(12, 24, 14, 24) //
|
||||||
QUANTIZE_ONE(16, 32, 6, 16)
|
QUANTIZE_ONE(16, 32, 6, 16) //
|
||||||
QUANTIZE_ONE(20, 40, 22, 26)
|
QUANTIZE_ONE(20, 40, 22, 26) //
|
||||||
QUANTIZE_ONE(24, 48, 18, 20)
|
QUANTIZE_ONE(24, 48, 18, 20) //
|
||||||
QUANTIZE_ONE(28, 56, 28, 30)
|
QUANTIZE_ONE(28, 56, 28, 30) //
|
||||||
|
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[sign] "=&r"(sign), [coeff] "=&r"(coeff), [level] "=&r"(level),
|
||||||
[sign]"=&r"(sign), [coeff]"=&r"(coeff),
|
[temp6] "=&r"(temp6), [ret] "+&r"(ret)
|
||||||
[level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret)
|
: [ppin] "r"(ppin), [pout] "r"(pout), [max_level1] "r"(max_level1),
|
||||||
: [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1),
|
[ppiq] "r"(ppiq), [max_level] "r"(max_level), [ppbias] "r"(ppbias),
|
||||||
[ppiq]"r"(ppiq), [max_level]"r"(max_level),
|
[ppzthresh] "r"(ppzthresh), [ppsharpen] "r"(ppsharpen), [ppq] "r"(ppq)
|
||||||
[ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh),
|
: "memory", "hi", "lo");
|
||||||
[ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq)
|
|
||||||
: "memory", "hi", "lo"
|
|
||||||
);
|
|
||||||
|
|
||||||
return (ret != 0);
|
return (ret != 0);
|
||||||
}
|
}
|
||||||
@@ -1341,6 +1350,7 @@ static int Quantize2Blocks_MIPSdspR2(int16_t in[32], int16_t out[32],
|
|||||||
// temp0..temp7 holds tmp[0]..tmp[15]
|
// temp0..temp7 holds tmp[0]..tmp[15]
|
||||||
// A, B, C, D - offset in bytes to load from in buffer
|
// A, B, C, D - offset in bytes to load from in buffer
|
||||||
// TEMP0, TEMP1 - registers for corresponding tmp elements
|
// TEMP0, TEMP1 - registers for corresponding tmp elements
|
||||||
|
// clang-format off
|
||||||
#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \
|
#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \
|
||||||
"lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \
|
"lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \
|
||||||
"lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \
|
"lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \
|
||||||
@@ -1373,26 +1383,26 @@ static int Quantize2Blocks_MIPSdspR2(int16_t in[32], int16_t out[32],
|
|||||||
"usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \
|
"usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \
|
||||||
"usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \
|
"usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \
|
||||||
"usw %[" #TEMP6 "], " #D "(%[out]) \n\t"
|
"usw %[" #TEMP6 "], " #D "(%[out]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void FTransformWHT_MIPSdspR2(const int16_t* WEBP_RESTRICT in,
|
static void FTransformWHT_MIPSdspR2(const int16_t* WEBP_RESTRICT in,
|
||||||
int16_t* WEBP_RESTRICT out) {
|
int16_t* WEBP_RESTRICT out) {
|
||||||
int temp0, temp1, temp2, temp3, temp4;
|
int temp0, temp1, temp2, temp3, temp4;
|
||||||
int temp5, temp6, temp7, temp8, temp9;
|
int temp5, temp6, temp7, temp8, temp9;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1)
|
HORIZONTAL_PASS_WHT(0, 32, 64, 96, temp0, temp1) //
|
||||||
HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3)
|
HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3) //
|
||||||
HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5)
|
HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5) //
|
||||||
HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7)
|
HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7) //
|
||||||
VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6)
|
VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6) //
|
||||||
VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7)
|
VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7) //
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [temp8] "=&r"(temp8),
|
||||||
[temp9]"=&r"(temp9)
|
[temp9] "=&r"(temp9)
|
||||||
: [in]"r"(in), [out]"r"(out)
|
: [in] "r"(in), [out] "r"(out)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef VERTICAL_PASS_WHT
|
#undef VERTICAL_PASS_WHT
|
||||||
@@ -1401,6 +1411,7 @@ static void FTransformWHT_MIPSdspR2(const int16_t* WEBP_RESTRICT in,
|
|||||||
// macro for converting coefficients to bin
|
// macro for converting coefficients to bin
|
||||||
// convert 8 coeffs at time
|
// convert 8 coeffs at time
|
||||||
// A, B, C, D - offsets in bytes to load from out buffer
|
// A, B, C, D - offsets in bytes to load from out buffer
|
||||||
|
// clang-format off
|
||||||
#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \
|
#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \
|
||||||
"ulw %[temp0], " #A "(%[out]) \n\t" \
|
"ulw %[temp0], " #A "(%[out]) \n\t" \
|
||||||
"ulw %[temp1], " #B "(%[out]) \n\t" \
|
"ulw %[temp1], " #B "(%[out]) \n\t" \
|
||||||
@@ -1466,12 +1477,13 @@ static void FTransformWHT_MIPSdspR2(const int16_t* WEBP_RESTRICT in,
|
|||||||
"lw %[temp8], 0(%[temp3]) \n\t" \
|
"lw %[temp8], 0(%[temp3]) \n\t" \
|
||||||
"addiu %[temp8], %[temp8], 1 \n\t" \
|
"addiu %[temp8], %[temp8], 1 \n\t" \
|
||||||
"sw %[temp8], 0(%[temp3]) \n\t"
|
"sw %[temp8], 0(%[temp3]) \n\t"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void CollectHistogram_MIPSdspR2(const uint8_t* ref, const uint8_t* pred,
|
static void CollectHistogram_MIPSdspR2(const uint8_t* ref, const uint8_t* pred,
|
||||||
int start_block, int end_block,
|
int start_block, int end_block,
|
||||||
VP8Histogram* const histo) {
|
VP8Histogram* const histo) {
|
||||||
int j;
|
int j;
|
||||||
int distribution[MAX_COEFF_THRESH + 1] = { 0 };
|
int distribution[MAX_COEFF_THRESH + 1] = {0};
|
||||||
const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH;
|
const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH;
|
||||||
for (j = start_block; j < end_block; ++j) {
|
for (j = start_block; j < end_block; ++j) {
|
||||||
int16_t out[16];
|
int16_t out[16];
|
||||||
@@ -1480,15 +1492,14 @@ static void CollectHistogram_MIPSdspR2(const uint8_t* ref, const uint8_t* pred,
|
|||||||
VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
|
VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
|
||||||
|
|
||||||
// Convert coefficients to bin.
|
// Convert coefficients to bin.
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12)
|
CONVERT_COEFFS_TO_BIN(0, 4, 8, 12) //
|
||||||
CONVERT_COEFFS_TO_BIN(16, 20, 24, 28)
|
CONVERT_COEFFS_TO_BIN(16, 20, 24, 28) //
|
||||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
: [temp0] "=&r"(temp0), [temp1] "=&r"(temp1), [temp2] "=&r"(temp2),
|
||||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
[temp3] "=&r"(temp3), [temp4] "=&r"(temp4), [temp5] "=&r"(temp5),
|
||||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
|
[temp6] "=&r"(temp6), [temp7] "=&r"(temp7), [temp8] "=&r"(temp8)
|
||||||
: [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff)
|
: [dist] "r"(distribution), [out] "r"(out), [max_coeff] "r"(max_coeff)
|
||||||
: "memory"
|
: "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
VP8SetHistogramData(distribution, histo);
|
VP8SetHistogramData(distribution, histo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,15 @@
|
|||||||
#if defined(WEBP_USE_MSA)
|
#if defined(WEBP_USE_MSA)
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "src/dsp/msa_macro.h"
|
#include "src/dsp/msa_macro.h"
|
||||||
#include "src/enc/vp8i_enc.h"
|
#include "src/enc/vp8i_enc.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Transforms
|
// Transforms
|
||||||
|
|
||||||
#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) do { \
|
#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) \
|
||||||
|
do { \
|
||||||
v4i32 a1_m, b1_m, c1_m, d1_m; \
|
v4i32 a1_m, b1_m, c1_m, d1_m; \
|
||||||
const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \
|
const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \
|
||||||
const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \
|
const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \
|
||||||
@@ -39,7 +41,7 @@
|
|||||||
d_tmp1_m = d_tmp1_m + in1; \
|
d_tmp1_m = d_tmp1_m + in1; \
|
||||||
d1_m = d_tmp1_m + d_tmp2_m; \
|
d1_m = d_tmp1_m + d_tmp2_m; \
|
||||||
BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
|
BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref,
|
static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref,
|
||||||
const int16_t* WEBP_RESTRICT in,
|
const int16_t* WEBP_RESTRICT in,
|
||||||
@@ -48,7 +50,7 @@ static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
|
v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
|
||||||
v4i32 res0, res1, res2, res3;
|
v4i32 res0, res1, res2, res3;
|
||||||
v16i8 dest0, dest1, dest2, dest3;
|
v16i8 dest0, dest1, dest2, dest3;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
|
|
||||||
LD_SH2(in, 8, input0, input1);
|
LD_SH2(in, 8, input0, input1);
|
||||||
UNPCK_SH_SW(input0, in0, in1);
|
UNPCK_SH_SW(input0, in0, in1);
|
||||||
@@ -59,10 +61,10 @@ static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
SRARI_W4_SW(vt0, vt1, vt2, vt3, 3);
|
SRARI_W4_SW(vt0, vt1, vt2, vt3, 3);
|
||||||
TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3);
|
TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3);
|
||||||
LD_SB4(ref, BPS, dest0, dest1, dest2, dest3);
|
LD_SB4(ref, BPS, dest0, dest1, dest2, dest3);
|
||||||
ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3,
|
ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, res0, res1,
|
||||||
res0, res1, res2, res3);
|
res2, res3);
|
||||||
ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3,
|
ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, res0, res1, res2,
|
||||||
res0, res1, res2, res3);
|
res3);
|
||||||
ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3);
|
ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3);
|
||||||
CLIP_SW4_0_255(res0, res1, res2, res3);
|
CLIP_SW4_0_255(res0, res1, res2, res3);
|
||||||
PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1);
|
PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1);
|
||||||
@@ -86,13 +88,13 @@ static void FTransform_MSA(const uint8_t* WEBP_RESTRICT src,
|
|||||||
uint32_t in0, in1, in2, in3;
|
uint32_t in0, in1, in2, in3;
|
||||||
v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
|
v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
|
||||||
v8i16 t0, t1, t2, t3;
|
v8i16 t0, t1, t2, t3;
|
||||||
v16u8 srcl0, srcl1, src0 = { 0 }, src1 = { 0 };
|
v16u8 srcl0, srcl1, src0 = {0}, src1 = {0};
|
||||||
const v8i16 mask0 = { 0, 4, 8, 12, 1, 5, 9, 13 };
|
const v8i16 mask0 = {0, 4, 8, 12, 1, 5, 9, 13};
|
||||||
const v8i16 mask1 = { 3, 7, 11, 15, 2, 6, 10, 14 };
|
const v8i16 mask1 = {3, 7, 11, 15, 2, 6, 10, 14};
|
||||||
const v8i16 mask2 = { 4, 0, 5, 1, 6, 2, 7, 3 };
|
const v8i16 mask2 = {4, 0, 5, 1, 6, 2, 7, 3};
|
||||||
const v8i16 mask3 = { 0, 4, 1, 5, 2, 6, 3, 7 };
|
const v8i16 mask3 = {0, 4, 1, 5, 2, 6, 3, 7};
|
||||||
const v8i16 cnst0 = { 2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352 };
|
const v8i16 cnst0 = {2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352};
|
||||||
const v8i16 cnst1 = { 5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217 };
|
const v8i16 cnst1 = {5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217};
|
||||||
|
|
||||||
LW4(src, BPS, in0, in1, in2, in3);
|
LW4(src, BPS, in0, in1, in2, in3);
|
||||||
INSERT_W4_UB(in0, in1, in2, in3, src0);
|
INSERT_W4_UB(in0, in1, in2, in3, src0);
|
||||||
@@ -136,29 +138,29 @@ static void FTransform_MSA(const uint8_t* WEBP_RESTRICT src,
|
|||||||
|
|
||||||
static void FTransformWHT_MSA(const int16_t* WEBP_RESTRICT in,
|
static void FTransformWHT_MSA(const int16_t* WEBP_RESTRICT in,
|
||||||
int16_t* WEBP_RESTRICT out) {
|
int16_t* WEBP_RESTRICT out) {
|
||||||
v8i16 in0 = { 0 };
|
v8i16 in0 = {0};
|
||||||
v8i16 in1 = { 0 };
|
v8i16 in1 = {0};
|
||||||
v8i16 tmp0, tmp1, tmp2, tmp3;
|
v8i16 tmp0, tmp1, tmp2, tmp3;
|
||||||
v8i16 out0, out1;
|
v8i16 out0, out1;
|
||||||
const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
|
const v8i16 mask0 = {0, 1, 2, 3, 8, 9, 10, 11};
|
||||||
const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
|
const v8i16 mask1 = {4, 5, 6, 7, 12, 13, 14, 15};
|
||||||
const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 };
|
const v8i16 mask2 = {0, 4, 8, 12, 1, 5, 9, 13};
|
||||||
const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 };
|
const v8i16 mask3 = {3, 7, 11, 15, 2, 6, 10, 14};
|
||||||
|
|
||||||
in0 = __msa_insert_h(in0, 0, in[ 0]);
|
in0 = __msa_insert_h(in0, 0, in[0]);
|
||||||
in0 = __msa_insert_h(in0, 1, in[ 64]);
|
in0 = __msa_insert_h(in0, 1, in[64]);
|
||||||
in0 = __msa_insert_h(in0, 2, in[128]);
|
in0 = __msa_insert_h(in0, 2, in[128]);
|
||||||
in0 = __msa_insert_h(in0, 3, in[192]);
|
in0 = __msa_insert_h(in0, 3, in[192]);
|
||||||
in0 = __msa_insert_h(in0, 4, in[ 16]);
|
in0 = __msa_insert_h(in0, 4, in[16]);
|
||||||
in0 = __msa_insert_h(in0, 5, in[ 80]);
|
in0 = __msa_insert_h(in0, 5, in[80]);
|
||||||
in0 = __msa_insert_h(in0, 6, in[144]);
|
in0 = __msa_insert_h(in0, 6, in[144]);
|
||||||
in0 = __msa_insert_h(in0, 7, in[208]);
|
in0 = __msa_insert_h(in0, 7, in[208]);
|
||||||
in1 = __msa_insert_h(in1, 0, in[ 48]);
|
in1 = __msa_insert_h(in1, 0, in[48]);
|
||||||
in1 = __msa_insert_h(in1, 1, in[112]);
|
in1 = __msa_insert_h(in1, 1, in[112]);
|
||||||
in1 = __msa_insert_h(in1, 2, in[176]);
|
in1 = __msa_insert_h(in1, 2, in[176]);
|
||||||
in1 = __msa_insert_h(in1, 3, in[240]);
|
in1 = __msa_insert_h(in1, 3, in[240]);
|
||||||
in1 = __msa_insert_h(in1, 4, in[ 32]);
|
in1 = __msa_insert_h(in1, 4, in[32]);
|
||||||
in1 = __msa_insert_h(in1, 5, in[ 96]);
|
in1 = __msa_insert_h(in1, 5, in[96]);
|
||||||
in1 = __msa_insert_h(in1, 6, in[160]);
|
in1 = __msa_insert_h(in1, 6, in[160]);
|
||||||
in1 = __msa_insert_h(in1, 7, in[224]);
|
in1 = __msa_insert_h(in1, 7, in[224]);
|
||||||
ADDSUB2(in0, in1, tmp0, tmp1);
|
ADDSUB2(in0, in1, tmp0, tmp1);
|
||||||
@@ -176,14 +178,14 @@ static int TTransform_MSA(const uint8_t* WEBP_RESTRICT in,
|
|||||||
const uint16_t* WEBP_RESTRICT w) {
|
const uint16_t* WEBP_RESTRICT w) {
|
||||||
int sum;
|
int sum;
|
||||||
uint32_t in0_m, in1_m, in2_m, in3_m;
|
uint32_t in0_m, in1_m, in2_m, in3_m;
|
||||||
v16i8 src0 = { 0 };
|
v16i8 src0 = {0};
|
||||||
v8i16 in0, in1, tmp0, tmp1, tmp2, tmp3;
|
v8i16 in0, in1, tmp0, tmp1, tmp2, tmp3;
|
||||||
v4i32 dst0, dst1;
|
v4i32 dst0, dst1;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
|
const v8i16 mask0 = {0, 1, 2, 3, 8, 9, 10, 11};
|
||||||
const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
|
const v8i16 mask1 = {4, 5, 6, 7, 12, 13, 14, 15};
|
||||||
const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 };
|
const v8i16 mask2 = {0, 4, 8, 12, 1, 5, 9, 13};
|
||||||
const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 };
|
const v8i16 mask3 = {3, 7, 11, 15, 2, 6, 10, 14};
|
||||||
|
|
||||||
LW4(in, BPS, in0_m, in1_m, in2_m, in3_m);
|
LW4(in, BPS, in0_m, in1_m, in2_m, in3_m);
|
||||||
INSERT_W4_SB(in0_m, in1_m, in2_m, in3_m, src0);
|
INSERT_W4_SB(in0_m, in1_m, in2_m, in3_m, src0);
|
||||||
@@ -233,14 +235,14 @@ static void CollectHistogram_MSA(const uint8_t* ref, const uint8_t* pred,
|
|||||||
int start_block, int end_block,
|
int start_block, int end_block,
|
||||||
VP8Histogram* const histo) {
|
VP8Histogram* const histo) {
|
||||||
int j;
|
int j;
|
||||||
int distribution[MAX_COEFF_THRESH + 1] = { 0 };
|
int distribution[MAX_COEFF_THRESH + 1] = {0};
|
||||||
for (j = start_block; j < end_block; ++j) {
|
for (j = start_block; j < end_block; ++j) {
|
||||||
int16_t out[16];
|
int16_t out[16];
|
||||||
VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
|
VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
v8i16 coeff0, coeff1;
|
v8i16 coeff0, coeff1;
|
||||||
const v8i16 zero = { 0 };
|
const v8i16 zero = {0};
|
||||||
const v8i16 max_coeff_thr = __msa_ldi_h(MAX_COEFF_THRESH);
|
const v8i16 max_coeff_thr = __msa_ldi_h(MAX_COEFF_THRESH);
|
||||||
LD_SH2(&out[0], 8, coeff0, coeff1);
|
LD_SH2(&out[0], 8, coeff0, coeff1);
|
||||||
coeff0 = __msa_add_a_h(coeff0, zero);
|
coeff0 = __msa_add_a_h(coeff0, zero);
|
||||||
@@ -269,7 +271,7 @@ static void CollectHistogram_MSA(const uint8_t* ref, const uint8_t* pred,
|
|||||||
// vertical
|
// vertical
|
||||||
static WEBP_INLINE void VE4(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void VE4(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
const v16u8 A1 = { 0 };
|
const v16u8 A1 = {0};
|
||||||
const uint64_t val_m = LD(top - 1);
|
const uint64_t val_m = LD(top - 1);
|
||||||
const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m);
|
const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m);
|
||||||
const v16u8 B = SLDI_UB(A, A, 1);
|
const v16u8 B = SLDI_UB(A, A, 1);
|
||||||
@@ -307,7 +309,7 @@ static WEBP_INLINE void DC4(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
static WEBP_INLINE void RD4(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void RD4(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
const v16u8 A2 = { 0 };
|
const v16u8 A2 = {0};
|
||||||
const uint64_t val_m = LD(top - 5);
|
const uint64_t val_m = LD(top - 5);
|
||||||
const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A2, 0, val_m);
|
const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A2, 0, val_m);
|
||||||
const v16u8 A = (v16u8)__msa_insert_b((v16i8)A1, 8, top[3]);
|
const v16u8 A = (v16u8)__msa_insert_b((v16i8)A1, 8, top[3]);
|
||||||
@@ -328,7 +330,7 @@ static WEBP_INLINE void RD4(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
static WEBP_INLINE void LD4(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void LD4(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
const v16u8 A1 = { 0 };
|
const v16u8 A1 = {0};
|
||||||
const uint64_t val_m = LD(top);
|
const uint64_t val_m = LD(top);
|
||||||
const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m);
|
const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m);
|
||||||
const v16u8 B = SLDI_UB(A, A, 1);
|
const v16u8 B = SLDI_UB(A, A, 1);
|
||||||
@@ -403,8 +405,7 @@ static WEBP_INLINE void HU4(uint8_t* WEBP_RESTRICT dst,
|
|||||||
DST(1, 0) = AVG3(I, J, K);
|
DST(1, 0) = AVG3(I, J, K);
|
||||||
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
||||||
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
||||||
DST(3, 2) = DST(2, 2) =
|
DST(3, 2) = DST(2, 2) = DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
||||||
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void HD4(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void HD4(uint8_t* WEBP_RESTRICT dst,
|
||||||
@@ -431,7 +432,7 @@ static WEBP_INLINE void HD4(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
static WEBP_INLINE void TM4(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void TM4(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 TL = (v8i16)__msa_fill_h(top[-1]);
|
const v8i16 TL = (v8i16)__msa_fill_h(top[-1]);
|
||||||
const v8i16 L0 = (v8i16)__msa_fill_h(top[-2]);
|
const v8i16 L0 = (v8i16)__msa_fill_h(top[-2]);
|
||||||
const v8i16 L1 = (v8i16)__msa_fill_h(top[-3]);
|
const v8i16 L1 = (v8i16)__msa_fill_h(top[-3]);
|
||||||
@@ -466,10 +467,11 @@ static void Intra4Preds_MSA(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
// luma 16x16 prediction
|
// luma 16x16 prediction
|
||||||
|
|
||||||
#define STORE16x16(out, dst) do { \
|
#define STORE16x16(out, dst) \
|
||||||
|
do { \
|
||||||
ST_UB8(out, out, out, out, out, out, out, out, dst + 0 * BPS, BPS); \
|
ST_UB8(out, out, out, out, out, out, out, out, dst + 0 * BPS, BPS); \
|
||||||
ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); \
|
ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static WEBP_INLINE void VerticalPred16x16(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void VerticalPred16x16(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
@@ -508,7 +510,7 @@ static WEBP_INLINE void TrueMotion16x16(uint8_t* WEBP_RESTRICT dst,
|
|||||||
if (top != NULL) {
|
if (top != NULL) {
|
||||||
int j;
|
int j;
|
||||||
v8i16 d1, d2;
|
v8i16 d1, d2;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 TL = (v8i16)__msa_fill_h(left[-1]);
|
const v8i16 TL = (v8i16)__msa_fill_h(left[-1]);
|
||||||
const v16u8 T = LD_UB(top);
|
const v16u8 T = LD_UB(top);
|
||||||
ILVRL_B2_SH(zero, T, d1, d2);
|
ILVRL_B2_SH(zero, T, d1, d2);
|
||||||
@@ -582,7 +584,8 @@ static void Intra16Preds_MSA(uint8_t* WEBP_RESTRICT dst,
|
|||||||
|
|
||||||
// Chroma 8x8 prediction
|
// Chroma 8x8 prediction
|
||||||
|
|
||||||
#define CALC_DC8(in, out) do { \
|
#define CALC_DC8(in, out) \
|
||||||
|
do { \
|
||||||
const v8u16 temp0 = __msa_hadd_u_h(in, in); \
|
const v8u16 temp0 = __msa_hadd_u_h(in, in); \
|
||||||
const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); \
|
const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); \
|
||||||
const v2i64 temp2 = (v2i64)__msa_hadd_u_d(temp1, temp1); \
|
const v2i64 temp2 = (v2i64)__msa_hadd_u_d(temp1, temp1); \
|
||||||
@@ -591,12 +594,13 @@ static void Intra16Preds_MSA(uint8_t* WEBP_RESTRICT dst,
|
|||||||
const v16i8 temp5 = (v16i8)__msa_srari_d(temp4, 4); \
|
const v16i8 temp5 = (v16i8)__msa_srari_d(temp4, 4); \
|
||||||
const v2i64 temp6 = (v2i64)__msa_splati_b(temp5, 0); \
|
const v2i64 temp6 = (v2i64)__msa_splati_b(temp5, 0); \
|
||||||
out = __msa_copy_s_d(temp6, 0); \
|
out = __msa_copy_s_d(temp6, 0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define STORE8x8(out, dst) do { \
|
#define STORE8x8(out, dst) \
|
||||||
|
do { \
|
||||||
SD4(out, out, out, out, dst + 0 * BPS, BPS); \
|
SD4(out, out, out, out, dst + 0 * BPS, BPS); \
|
||||||
SD4(out, out, out, out, dst + 4 * BPS, BPS); \
|
SD4(out, out, out, out, dst + 4 * BPS, BPS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static WEBP_INLINE void VerticalPred8x8(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void VerticalPred8x8(uint8_t* WEBP_RESTRICT dst,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
@@ -640,7 +644,7 @@ static WEBP_INLINE void TrueMotion8x8(uint8_t* WEBP_RESTRICT dst,
|
|||||||
int j;
|
int j;
|
||||||
const v8i16 TL = (v8i16)__msa_fill_h(left[-1]);
|
const v8i16 TL = (v8i16)__msa_fill_h(left[-1]);
|
||||||
const v16u8 T1 = LD_UB(top);
|
const v16u8 T1 = LD_UB(top);
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1);
|
const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1);
|
||||||
const v8i16 d = T - TL;
|
const v8i16 d = T - TL;
|
||||||
for (j = 0; j < 8; j += 4) {
|
for (j = 0; j < 8; j += 4) {
|
||||||
@@ -677,7 +681,7 @@ static WEBP_INLINE void DCMode8x8(uint8_t* WEBP_RESTRICT dst,
|
|||||||
const uint8_t* WEBP_RESTRICT left,
|
const uint8_t* WEBP_RESTRICT left,
|
||||||
const uint8_t* WEBP_RESTRICT top) {
|
const uint8_t* WEBP_RESTRICT top) {
|
||||||
uint64_t out;
|
uint64_t out;
|
||||||
v16u8 src = { 0 };
|
v16u8 src = {0};
|
||||||
if (top != NULL && left != NULL) {
|
if (top != NULL && left != NULL) {
|
||||||
const uint64_t left_m = LD(left);
|
const uint64_t left_m = LD(left);
|
||||||
const uint64_t top_m = LD(top);
|
const uint64_t top_m = LD(top);
|
||||||
@@ -719,7 +723,8 @@ static void IntraChromaPreds_MSA(uint8_t* WEBP_RESTRICT dst,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Metric
|
// Metric
|
||||||
|
|
||||||
#define PACK_DOTP_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \
|
#define PACK_DOTP_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) \
|
||||||
|
do { \
|
||||||
v16u8 tmp0, tmp1; \
|
v16u8 tmp0, tmp1; \
|
||||||
v8i16 tmp2, tmp3; \
|
v8i16 tmp2, tmp3; \
|
||||||
ILVRL_B2_UB(in0, in1, tmp0, tmp1); \
|
ILVRL_B2_UB(in0, in1, tmp0, tmp1); \
|
||||||
@@ -728,9 +733,10 @@ static void IntraChromaPreds_MSA(uint8_t* WEBP_RESTRICT dst,
|
|||||||
ILVRL_B2_UB(in2, in3, tmp0, tmp1); \
|
ILVRL_B2_UB(in2, in3, tmp0, tmp1); \
|
||||||
HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
|
HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
|
||||||
DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \
|
DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define PACK_DPADD_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \
|
#define PACK_DPADD_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) \
|
||||||
|
do { \
|
||||||
v16u8 tmp0, tmp1; \
|
v16u8 tmp0, tmp1; \
|
||||||
v8i16 tmp2, tmp3; \
|
v8i16 tmp2, tmp3; \
|
||||||
ILVRL_B2_UB(in0, in1, tmp0, tmp1); \
|
ILVRL_B2_UB(in0, in1, tmp0, tmp1); \
|
||||||
@@ -739,7 +745,7 @@ static void IntraChromaPreds_MSA(uint8_t* WEBP_RESTRICT dst,
|
|||||||
ILVRL_B2_UB(in2, in3, tmp0, tmp1); \
|
ILVRL_B2_UB(in2, in3, tmp0, tmp1); \
|
||||||
HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
|
HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
|
||||||
DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \
|
DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int SSE16x16_MSA(const uint8_t* WEBP_RESTRICT a,
|
static int SSE16x16_MSA(const uint8_t* WEBP_RESTRICT a,
|
||||||
const uint8_t* WEBP_RESTRICT b) {
|
const uint8_t* WEBP_RESTRICT b) {
|
||||||
@@ -814,7 +820,7 @@ static int SSE4x4_MSA(const uint8_t* WEBP_RESTRICT a,
|
|||||||
const uint8_t* WEBP_RESTRICT b) {
|
const uint8_t* WEBP_RESTRICT b) {
|
||||||
uint32_t sum = 0;
|
uint32_t sum = 0;
|
||||||
uint32_t src0, src1, src2, src3, ref0, ref1, ref2, ref3;
|
uint32_t src0, src1, src2, src3, ref0, ref1, ref2, ref3;
|
||||||
v16u8 src = { 0 }, ref = { 0 }, tmp0, tmp1;
|
v16u8 src = {0}, ref = {0}, tmp0, tmp1;
|
||||||
v8i16 diff0, diff1;
|
v8i16 diff0, diff1;
|
||||||
v4i32 out0, out1;
|
v4i32 out0, out1;
|
||||||
|
|
||||||
@@ -839,9 +845,9 @@ static int QuantizeBlock_MSA(int16_t in[16], int16_t out[16],
|
|||||||
v8i16 in0, in1, sh0, sh1, out0, out1;
|
v8i16 in0, in1, sh0, sh1, out0, out1;
|
||||||
v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, sign0, sign1;
|
v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, sign0, sign1;
|
||||||
v4i32 s0, s1, s2, s3, b0, b1, b2, b3, t0, t1, t2, t3;
|
v4i32 s0, s1, s2, s3, b0, b1, b2, b3, t0, t1, t2, t3;
|
||||||
const v8i16 zero = { 0 };
|
const v8i16 zero = {0};
|
||||||
const v8i16 zigzag0 = { 0, 1, 4, 8, 5, 2, 3, 6 };
|
const v8i16 zigzag0 = {0, 1, 4, 8, 5, 2, 3, 6};
|
||||||
const v8i16 zigzag1 = { 9, 12, 13, 10, 7, 11, 14, 15 };
|
const v8i16 zigzag1 = {9, 12, 13, 10, 7, 11, 14, 15};
|
||||||
const v8i16 maxlevel = __msa_fill_h(MAX_LEVEL);
|
const v8i16 maxlevel = __msa_fill_h(MAX_LEVEL);
|
||||||
|
|
||||||
LD_SH2(&in[0], 8, in0, in1);
|
LD_SH2(&in[0], 8, in0, in1);
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ static void ITransformOne_NEON(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
const int16_t* WEBP_RESTRICT in,
|
const int16_t* WEBP_RESTRICT in,
|
||||||
uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
const int kBPS = BPS;
|
const int kBPS = BPS;
|
||||||
const int16_t kC1C2[] = { kC1, kC2, 0, 0 };
|
const int16_t kC1C2[] = {kC1, kC2, 0, 0};
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"vld1.16 {q1, q2}, [%[in]] \n"
|
"vld1.16 {q1, q2}, [%[in]] \n"
|
||||||
"vld1.16 {d0}, [%[kC1C2]] \n"
|
"vld1.16 {d0}, [%[kC1C2]] \n"
|
||||||
|
|
||||||
@@ -272,24 +272,19 @@ static uint8x16_t Load4x4_NEON(const uint8_t* src) {
|
|||||||
|
|
||||||
#if defined(WEBP_USE_INTRINSICS)
|
#if defined(WEBP_USE_INTRINSICS)
|
||||||
|
|
||||||
static WEBP_INLINE void Transpose4x4_S16_NEON(const int16x4_t A,
|
static WEBP_INLINE void Transpose4x4_S16_NEON(
|
||||||
const int16x4_t B,
|
const int16x4_t A, const int16x4_t B, const int16x4_t C, const int16x4_t D,
|
||||||
const int16x4_t C,
|
int16x8_t* const out01, int16x8_t* const out32) {
|
||||||
const int16x4_t D,
|
|
||||||
int16x8_t* const out01,
|
|
||||||
int16x8_t* const out32) {
|
|
||||||
const int16x4x2_t AB = vtrn_s16(A, B);
|
const int16x4x2_t AB = vtrn_s16(A, B);
|
||||||
const int16x4x2_t CD = vtrn_s16(C, D);
|
const int16x4x2_t CD = vtrn_s16(C, D);
|
||||||
const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]),
|
const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]),
|
||||||
vreinterpret_s32_s16(CD.val[0]));
|
vreinterpret_s32_s16(CD.val[0]));
|
||||||
const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]),
|
const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]),
|
||||||
vreinterpret_s32_s16(CD.val[1]));
|
vreinterpret_s32_s16(CD.val[1]));
|
||||||
*out01 = vreinterpretq_s16_s64(
|
*out01 = vreinterpretq_s16_s64(vcombine_s64(
|
||||||
vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]),
|
vreinterpret_s64_s32(tmp02.val[0]), vreinterpret_s64_s32(tmp13.val[0])));
|
||||||
vreinterpret_s64_s32(tmp13.val[0])));
|
*out32 = vreinterpretq_s16_s64(vcombine_s64(
|
||||||
*out32 = vreinterpretq_s16_s64(
|
vreinterpret_s64_s32(tmp13.val[1]), vreinterpret_s64_s32(tmp02.val[1])));
|
||||||
vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]),
|
|
||||||
vreinterpret_s64_s32(tmp02.val[1])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int16x8_t DiffU8ToS16_NEON(const uint8x8_t a,
|
static WEBP_INLINE int16x8_t DiffU8ToS16_NEON(const uint8x8_t a,
|
||||||
@@ -318,10 +313,10 @@ static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1)
|
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 a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2)
|
||||||
const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3);
|
const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3);
|
||||||
const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2),
|
const int16x4_t tmp0 =
|
||||||
vget_high_s16(a0a1_2));
|
vadd_s16(vget_low_s16(a0a1_2), vget_high_s16(a0a1_2));
|
||||||
const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2),
|
const int16x4_t tmp2 =
|
||||||
vget_high_s16(a0a1_2));
|
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 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_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 a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352);
|
||||||
@@ -358,15 +353,11 @@ static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm
|
// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm
|
||||||
static const int16_t kCoeff16[] = {
|
static const int16_t kCoeff16[] = {5352, 5352, 5352, 5352,
|
||||||
5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217
|
2217, 2217, 2217, 2217};
|
||||||
};
|
static const int32_t kCoeff32[] = {1812, 1812, 1812, 1812, 937, 937,
|
||||||
static const int32_t kCoeff32[] = {
|
937, 937, 12000, 12000, 12000, 12000,
|
||||||
1812, 1812, 1812, 1812,
|
51000, 51000, 51000, 51000};
|
||||||
937, 937, 937, 937,
|
|
||||||
12000, 12000, 12000, 12000,
|
|
||||||
51000, 51000, 51000, 51000
|
|
||||||
};
|
|
||||||
|
|
||||||
static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
||||||
const uint8_t* WEBP_RESTRICT ref,
|
const uint8_t* WEBP_RESTRICT ref,
|
||||||
@@ -377,7 +368,7 @@ static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
const int16_t* coeff16 = kCoeff16;
|
const int16_t* coeff16 = kCoeff16;
|
||||||
const int32_t* coeff32 = kCoeff32;
|
const int32_t* coeff32 = kCoeff32;
|
||||||
|
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
// load src into q4, q5 in high half
|
// load src into q4, q5 in high half
|
||||||
"vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n"
|
"vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n"
|
||||||
"vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n"
|
"vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n"
|
||||||
@@ -420,9 +411,11 @@ static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
"vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3
|
"vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3
|
||||||
|
|
||||||
"vadd.s16 d0, d4, d5 \n" // a0 + a1
|
"vadd.s16 d0, d4, d5 \n" // a0 + a1
|
||||||
"vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3
|
"vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) <<
|
||||||
|
// 3
|
||||||
"vsub.s16 d2, d4, d5 \n" // a0 - a1
|
"vsub.s16 d2, d4, d5 \n" // a0 - a1
|
||||||
"vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3
|
"vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1)
|
||||||
|
// << 3
|
||||||
|
|
||||||
"vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812
|
"vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812
|
||||||
"vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937
|
"vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937
|
||||||
@@ -460,8 +453,10 @@ static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
"vshr.s16 d0, d0, #4 \n"
|
"vshr.s16 d0, d0, #4 \n"
|
||||||
"vshr.s16 d2, d2, #4 \n"
|
"vshr.s16 d2, d2, #4 \n"
|
||||||
|
|
||||||
"vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000
|
"vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 +
|
||||||
"vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000
|
// 12000
|
||||||
|
"vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 +
|
||||||
|
// 51000
|
||||||
|
|
||||||
"vmvn d4, d4 \n" // !(d1 == 0)
|
"vmvn d4, d4 \n" // !(d1 == 0)
|
||||||
// op[4] = (c1*2217 + d1*5352 + 12000)>>16
|
// op[4] = (c1*2217 + d1*5352 + 12000)>>16
|
||||||
@@ -484,10 +479,11 @@ static void FTransform_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LOAD_LANE_16b(VALUE, LANE) do { \
|
#define LOAD_LANE_16b(VALUE, LANE) \
|
||||||
|
do { \
|
||||||
(VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \
|
(VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \
|
||||||
src += stride; \
|
src += stride; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void FTransformWHT_NEON(const int16_t* WEBP_RESTRICT src,
|
static void FTransformWHT_NEON(const int16_t* WEBP_RESTRICT src,
|
||||||
int16_t* WEBP_RESTRICT out) {
|
int16_t* WEBP_RESTRICT out) {
|
||||||
@@ -586,8 +582,8 @@ static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16_NEON(int16x8x4_t q4_in) {
|
|||||||
return q4_in;
|
return q4_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int16x8x4_t DistoHorizontalPass_NEON(
|
static WEBP_INLINE int16x8x4_t
|
||||||
const int16x8x4_t q4_in) {
|
DistoHorizontalPass_NEON(const int16x8x4_t q4_in) {
|
||||||
// {a0, a1} = {in[0] + in[2], in[1] + in[3]}
|
// {a0, a1} = {in[0] + in[2], in[1] + in[3]}
|
||||||
// {a3, a2} = {in[0] - in[2], in[1] - in[3]}
|
// {a3, a2} = {in[0] - in[2], in[1] - in[3]}
|
||||||
const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]);
|
const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]);
|
||||||
@@ -599,26 +595,24 @@ static WEBP_INLINE int16x8x4_t DistoHorizontalPass_NEON(
|
|||||||
// tmp[1] = a3 + a2
|
// tmp[1] = a3 + a2
|
||||||
// tmp[2] = a3 - a2
|
// tmp[2] = a3 - a2
|
||||||
// tmp[3] = a0 - a1
|
// tmp[3] = a0 - a1
|
||||||
INIT_VECTOR4(q4_out,
|
INIT_VECTOR4(q4_out, vabsq_s16(vaddq_s16(q_a0, q_a1)),
|
||||||
vabsq_s16(vaddq_s16(q_a0, q_a1)),
|
vabsq_s16(vaddq_s16(q_a3, q_a2)), vabdq_s16(q_a3, q_a2),
|
||||||
vabsq_s16(vaddq_s16(q_a3, q_a2)),
|
vabdq_s16(q_a0, q_a1));
|
||||||
vabdq_s16(q_a3, q_a2), vabdq_s16(q_a0, q_a1));
|
|
||||||
return q4_out;
|
return q4_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int16x8x4_t DistoVerticalPass_NEON(const uint8x8x4_t q4_in) {
|
static WEBP_INLINE int16x8x4_t DistoVerticalPass_NEON(const uint8x8x4_t q4_in) {
|
||||||
const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[0],
|
const int16x8_t q_a0 =
|
||||||
q4_in.val[2]));
|
vreinterpretq_s16_u16(vaddl_u8(q4_in.val[0], q4_in.val[2]));
|
||||||
const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[1],
|
const int16x8_t q_a1 =
|
||||||
q4_in.val[3]));
|
vreinterpretq_s16_u16(vaddl_u8(q4_in.val[1], q4_in.val[3]));
|
||||||
const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[1],
|
const int16x8_t q_a2 =
|
||||||
q4_in.val[3]));
|
vreinterpretq_s16_u16(vsubl_u8(q4_in.val[1], q4_in.val[3]));
|
||||||
const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[0],
|
const int16x8_t q_a3 =
|
||||||
q4_in.val[2]));
|
vreinterpretq_s16_u16(vsubl_u8(q4_in.val[0], q4_in.val[2]));
|
||||||
int16x8x4_t q4_out;
|
int16x8x4_t q4_out;
|
||||||
|
|
||||||
INIT_VECTOR4(q4_out,
|
INIT_VECTOR4(q4_out, vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2),
|
||||||
vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2),
|
|
||||||
vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1));
|
vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1));
|
||||||
return q4_out;
|
return q4_out;
|
||||||
}
|
}
|
||||||
@@ -627,8 +621,7 @@ static WEBP_INLINE int16x4x4_t DistoLoadW_NEON(const uint16_t* w) {
|
|||||||
const uint16x8_t q_w07 = vld1q_u16(&w[0]);
|
const uint16x8_t q_w07 = vld1q_u16(&w[0]);
|
||||||
const uint16x8_t q_w8f = vld1q_u16(&w[8]);
|
const uint16x8_t q_w8f = vld1q_u16(&w[8]);
|
||||||
int16x4x4_t d4_w;
|
int16x4x4_t d4_w;
|
||||||
INIT_VECTOR4(d4_w,
|
INIT_VECTOR4(d4_w, vget_low_s16(vreinterpretq_s16_u16(q_w07)),
|
||||||
vget_low_s16(vreinterpretq_s16_u16(q_w07)),
|
|
||||||
vget_high_s16(vreinterpretq_s16_u16(q_w07)),
|
vget_high_s16(vreinterpretq_s16_u16(q_w07)),
|
||||||
vget_low_s16(vreinterpretq_s16_u16(q_w8f)),
|
vget_low_s16(vreinterpretq_s16_u16(q_w8f)),
|
||||||
vget_high_s16(vreinterpretq_s16_u16(q_w8f)));
|
vget_high_s16(vreinterpretq_s16_u16(q_w8f)));
|
||||||
@@ -683,8 +676,7 @@ static int Disto4x4_NEON(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1);
|
LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1);
|
||||||
LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1);
|
LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1);
|
||||||
LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1);
|
LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1);
|
||||||
INIT_VECTOR4(d4_in,
|
INIT_VECTOR4(d4_in, vreinterpret_u8_u32(d_in_ab_0123),
|
||||||
vreinterpret_u8_u32(d_in_ab_0123),
|
|
||||||
vreinterpret_u8_u32(d_in_ab_4567),
|
vreinterpret_u8_u32(d_in_ab_4567),
|
||||||
vreinterpret_u8_u32(d_in_ab_89ab),
|
vreinterpret_u8_u32(d_in_ab_89ab),
|
||||||
vreinterpret_u8_u32(d_in_ab_cdef));
|
vreinterpret_u8_u32(d_in_ab_cdef));
|
||||||
@@ -729,7 +721,7 @@ static void CollectHistogram_NEON(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
VP8Histogram* WEBP_RESTRICT const histo) {
|
VP8Histogram* WEBP_RESTRICT const histo) {
|
||||||
const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH);
|
const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH);
|
||||||
int j;
|
int j;
|
||||||
int distribution[MAX_COEFF_THRESH + 1] = { 0 };
|
int distribution[MAX_COEFF_THRESH + 1] = {0};
|
||||||
for (j = start_block; j < end_block; ++j) {
|
for (j = start_block; j < end_block; ++j) {
|
||||||
int16_t out[16];
|
int16_t out[16];
|
||||||
FTransform_NEON(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
|
FTransform_NEON(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
|
||||||
@@ -762,10 +754,10 @@ static WEBP_INLINE void AccumulateSSE16_NEON(
|
|||||||
const uint8x16_t a0 = vld1q_u8(a);
|
const uint8x16_t a0 = vld1q_u8(a);
|
||||||
const uint8x16_t b0 = vld1q_u8(b);
|
const uint8x16_t b0 = vld1q_u8(b);
|
||||||
const uint8x16_t abs_diff = vabdq_u8(a0, b0);
|
const uint8x16_t abs_diff = vabdq_u8(a0, b0);
|
||||||
const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff),
|
const uint16x8_t prod1 =
|
||||||
vget_low_u8(abs_diff));
|
vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff));
|
||||||
const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff),
|
const uint16x8_t prod2 =
|
||||||
vget_high_u8(abs_diff));
|
vmull_u8(vget_high_u8(abs_diff), vget_high_u8(abs_diff));
|
||||||
/* pair-wise adds and widen */
|
/* pair-wise adds and widen */
|
||||||
const uint32x4_t sum1 = vpaddlq_u16(prod1);
|
const uint32x4_t sum1 = vpaddlq_u16(prod1);
|
||||||
const uint32x4_t sum2 = vpaddlq_u16(prod2);
|
const uint32x4_t sum2 = vpaddlq_u16(prod2);
|
||||||
@@ -823,10 +815,10 @@ static int SSE4x4_NEON(const uint8_t* WEBP_RESTRICT a,
|
|||||||
const uint8x16_t a0 = Load4x4_NEON(a);
|
const uint8x16_t a0 = Load4x4_NEON(a);
|
||||||
const uint8x16_t b0 = Load4x4_NEON(b);
|
const uint8x16_t b0 = Load4x4_NEON(b);
|
||||||
const uint8x16_t abs_diff = vabdq_u8(a0, b0);
|
const uint8x16_t abs_diff = vabdq_u8(a0, b0);
|
||||||
const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff),
|
const uint16x8_t prod1 =
|
||||||
vget_low_u8(abs_diff));
|
vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff));
|
||||||
const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff),
|
const uint16x8_t prod2 =
|
||||||
vget_high_u8(abs_diff));
|
vmull_u8(vget_high_u8(abs_diff), vget_high_u8(abs_diff));
|
||||||
/* pair-wise adds and widen */
|
/* pair-wise adds and widen */
|
||||||
const uint32x4_t sum1 = vpaddlq_u16(prod1);
|
const uint32x4_t sum1 = vpaddlq_u16(prod1);
|
||||||
const uint32x4_t sum2 = vpaddlq_u16(prod2);
|
const uint32x4_t sum2 = vpaddlq_u16(prod2);
|
||||||
@@ -855,8 +847,8 @@ static int16x8_t Quantize_NEON(int16_t* WEBP_RESTRICT const in,
|
|||||||
const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_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 m2 = vhaddq_u32(m0, bias0);
|
||||||
const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1
|
const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1
|
||||||
const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16),
|
const uint16x8_t c0 =
|
||||||
vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1
|
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 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 c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign);
|
||||||
const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign
|
const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign
|
||||||
@@ -866,12 +858,10 @@ static int16x8_t Quantize_NEON(int16_t* WEBP_RESTRICT const in,
|
|||||||
return c3;
|
return c3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t kShuffles[4][8] = {
|
static const uint8_t kShuffles[4][8] = {{0, 1, 2, 3, 8, 9, 16, 17},
|
||||||
{ 0, 1, 2, 3, 8, 9, 16, 17 },
|
{10, 11, 4, 5, 6, 7, 12, 13},
|
||||||
{ 10, 11, 4, 5, 6, 7, 12, 13 },
|
{18, 19, 24, 25, 26, 27, 20, 21},
|
||||||
{ 18, 19, 24, 25, 26, 27, 20, 21 },
|
{14, 15, 22, 23, 28, 29, 30, 31}};
|
||||||
{ 14, 15, 22, 23, 28, 29, 30, 31 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int QuantizeBlock_NEON(int16_t in[16], int16_t out[16],
|
static int QuantizeBlock_NEON(int16_t in[16], int16_t out[16],
|
||||||
const VP8Matrix* WEBP_RESTRICT const mtx) {
|
const VP8Matrix* WEBP_RESTRICT const mtx) {
|
||||||
@@ -880,24 +870,21 @@ static int QuantizeBlock_NEON(int16_t in[16], int16_t out[16],
|
|||||||
uint8x8x4_t shuffles;
|
uint8x8x4_t shuffles;
|
||||||
// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
|
// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
|
||||||
// non-standard versions there.
|
// non-standard versions there.
|
||||||
#if defined(__APPLE__) && WEBP_AARCH64 && \
|
#if defined(__APPLE__) && WEBP_AARCH64 && defined(__apple_build_version__) && \
|
||||||
defined(__apple_build_version__) && (__apple_build_version__< 6020037)
|
(__apple_build_version__ < 6020037)
|
||||||
uint8x16x2_t all_out;
|
uint8x16x2_t all_out;
|
||||||
INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
|
INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
|
||||||
INIT_VECTOR4(shuffles,
|
INIT_VECTOR4(shuffles, vtbl2q_u8(all_out, vld1_u8(kShuffles[0])),
|
||||||
vtbl2q_u8(all_out, vld1_u8(kShuffles[0])),
|
|
||||||
vtbl2q_u8(all_out, vld1_u8(kShuffles[1])),
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[1])),
|
||||||
vtbl2q_u8(all_out, vld1_u8(kShuffles[2])),
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[2])),
|
||||||
vtbl2q_u8(all_out, vld1_u8(kShuffles[3])));
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[3])));
|
||||||
#else
|
#else
|
||||||
uint8x8x4_t all_out;
|
uint8x8x4_t all_out;
|
||||||
INIT_VECTOR4(all_out,
|
INIT_VECTOR4(all_out, vreinterpret_u8_s16(vget_low_s16(out0)),
|
||||||
vreinterpret_u8_s16(vget_low_s16(out0)),
|
|
||||||
vreinterpret_u8_s16(vget_high_s16(out0)),
|
vreinterpret_u8_s16(vget_high_s16(out0)),
|
||||||
vreinterpret_u8_s16(vget_low_s16(out1)),
|
vreinterpret_u8_s16(vget_low_s16(out1)),
|
||||||
vreinterpret_u8_s16(vget_high_s16(out1)));
|
vreinterpret_u8_s16(vget_high_s16(out1)));
|
||||||
INIT_VECTOR4(shuffles,
|
INIT_VECTOR4(shuffles, vtbl4_u8(all_out, vld1_u8(kShuffles[0])),
|
||||||
vtbl4_u8(all_out, vld1_u8(kShuffles[0])),
|
|
||||||
vtbl4_u8(all_out, vld1_u8(kShuffles[1])),
|
vtbl4_u8(all_out, vld1_u8(kShuffles[1])),
|
||||||
vtbl4_u8(all_out, vld1_u8(kShuffles[2])),
|
vtbl4_u8(all_out, vld1_u8(kShuffles[2])),
|
||||||
vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
|
vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
|
||||||
@@ -960,8 +947,7 @@ static WEBP_INLINE uint8x16x4_t Vld1qU8x4(const uint8_t* ptr) {
|
|||||||
return vld1q_u8_x4(ptr);
|
return vld1q_u8_x4(ptr);
|
||||||
#else
|
#else
|
||||||
uint8x16x4_t res;
|
uint8x16x4_t res;
|
||||||
INIT_VECTOR4(res,
|
INIT_VECTOR4(res, vld1q_u8(ptr + 0 * 16), vld1q_u8(ptr + 1 * 16),
|
||||||
vld1q_u8(ptr + 0 * 16), vld1q_u8(ptr + 1 * 16),
|
|
||||||
vld1q_u8(ptr + 2 * 16), vld1q_u8(ptr + 3 * 16));
|
vld1q_u8(ptr + 2 * 16), vld1q_u8(ptr + 3 * 16));
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
@@ -976,22 +962,19 @@ static void Intra4Preds_NEON(uint8_t* WEBP_RESTRICT dst,
|
|||||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12,
|
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12,
|
||||||
3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0,
|
3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0,
|
||||||
4, 20, 21, 22, 3, 18, 2, 17, 3, 19, 4, 20, 2, 17, 1, 16,
|
4, 20, 21, 22, 3, 18, 2, 17, 3, 19, 4, 20, 2, 17, 1, 16,
|
||||||
2, 18, 3, 19, 1, 16, 31, 31, 1, 17, 2, 18, 31, 31, 31, 31
|
2, 18, 3, 19, 1, 16, 31, 31, 1, 17, 2, 18, 31, 31, 31, 31};
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t kLookupTbl2[64] = {
|
static const uint8_t kLookupTbl2[64] = {
|
||||||
20, 21, 22, 23, 5, 6, 7, 8, 22, 23, 24, 25, 6, 7, 8, 9,
|
20, 21, 22, 23, 5, 6, 7, 8, 22, 23, 24, 25, 6, 7, 8, 9,
|
||||||
19, 20, 21, 22, 20, 21, 22, 23, 23, 24, 25, 26, 22, 23, 24, 25,
|
19, 20, 21, 22, 20, 21, 22, 23, 23, 24, 25, 26, 22, 23, 24, 25,
|
||||||
18, 19, 20, 21, 19, 5, 6, 7, 24, 25, 26, 27, 7, 8, 9, 26,
|
18, 19, 20, 21, 19, 5, 6, 7, 24, 25, 26, 27, 7, 8, 9, 26,
|
||||||
17, 18, 19, 20, 18, 20, 21, 22, 25, 26, 27, 28, 23, 24, 25, 27
|
17, 18, 19, 20, 18, 20, 21, 22, 25, 26, 27, 28, 23, 24, 25, 27};
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t kLookupTbl3[64] = {
|
static const uint8_t kLookupTbl3[64] = {
|
||||||
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 19, 19, 19, 19,
|
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 19, 19, 19, 19,
|
||||||
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 18, 18, 18, 18,
|
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 18, 18, 18, 18,
|
||||||
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 17, 17, 17, 17,
|
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 17, 17, 17, 17,
|
||||||
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 16, 16, 16, 16
|
30, 30, 30, 30, 0, 0, 0, 0, 21, 22, 23, 24, 16, 16, 16, 16};
|
||||||
};
|
|
||||||
|
|
||||||
const uint8x16x4_t lookup_avgs1 = Vld1qU8x4(kLookupTbl1);
|
const uint8x16x4_t lookup_avgs1 = Vld1qU8x4(kLookupTbl1);
|
||||||
const uint8x16x4_t lookup_avgs2 = Vld1qU8x4(kLookupTbl2);
|
const uint8x16x4_t lookup_avgs2 = Vld1qU8x4(kLookupTbl2);
|
||||||
|
|||||||
@@ -14,9 +14,8 @@
|
|||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
|
|
||||||
#if defined(WEBP_USE_SSE2)
|
#if defined(WEBP_USE_SSE2)
|
||||||
#include <emmintrin.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <emmintrin.h>
|
||||||
#include <stdlib.h> // for abs()
|
#include <stdlib.h> // for abs()
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -50,10 +49,10 @@ static void ITransform_One_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
// variable and the multiplication of that variable by the associated
|
// variable and the multiplication of that variable by the associated
|
||||||
// constant:
|
// constant:
|
||||||
// (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
|
// (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
|
||||||
const __m128i k1k2 = _mm_set_epi16(-30068, -30068, -30068, -30068,
|
const __m128i k1k2 =
|
||||||
20091, 20091, 20091, 20091);
|
_mm_set_epi16(-30068, -30068, -30068, -30068, 20091, 20091, 20091, 20091);
|
||||||
const __m128i k2k1 = _mm_set_epi16(20091, 20091, 20091, 20091,
|
const __m128i k2k1 =
|
||||||
-30068, -30068, -30068, -30068);
|
_mm_set_epi16(20091, 20091, 20091, 20091, -30068, -30068, -30068, -30068);
|
||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
const __m128i zero_four = _mm_set_epi16(0, 0, 0, 0, 4, 4, 4, 4);
|
const __m128i zero_four = _mm_set_epi16(0, 0, 0, 0, 4, 4, 4, 4);
|
||||||
__m128i T01, T23;
|
__m128i T01, T23;
|
||||||
@@ -172,7 +171,7 @@ static void ITransform_One_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
// Unsigned saturate to 8b.
|
// Unsigned saturate to 8b.
|
||||||
ref0123 = _mm_packus_epi16(ref01, ref23);
|
ref0123 = _mm_packus_epi16(ref01, ref23);
|
||||||
|
|
||||||
_mm_storeu_si128((__m128i *)buf, ref0123);
|
_mm_storeu_si128((__m128i*)buf, ref0123);
|
||||||
|
|
||||||
// Store four bytes/pixels per line.
|
// Store four bytes/pixels per line.
|
||||||
WebPInt32ToMem(&dst[0 * BPS], buf[0]);
|
WebPInt32ToMem(&dst[0 * BPS], buf[0]);
|
||||||
@@ -325,8 +324,7 @@ static void ITransform_Two_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
// Does one or two inverse transforms.
|
// Does one or two inverse transforms.
|
||||||
static void ITransform_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
static void ITransform_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
||||||
const int16_t* WEBP_RESTRICT in,
|
const int16_t* WEBP_RESTRICT in,
|
||||||
uint8_t* WEBP_RESTRICT dst,
|
uint8_t* WEBP_RESTRICT dst, int do_two) {
|
||||||
int do_two) {
|
|
||||||
if (do_two) {
|
if (do_two) {
|
||||||
ITransform_Two_SSE2(ref, in, dst);
|
ITransform_Two_SSE2(ref, in, dst);
|
||||||
} else {
|
} else {
|
||||||
@@ -336,17 +334,16 @@ static void ITransform_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
|
|
||||||
static void FTransformPass1_SSE2(const __m128i* const in01,
|
static void FTransformPass1_SSE2(const __m128i* const in01,
|
||||||
const __m128i* const in23,
|
const __m128i* const in23,
|
||||||
__m128i* const out01,
|
__m128i* const out01, __m128i* const out32) {
|
||||||
__m128i* const out32) {
|
|
||||||
const __m128i k937 = _mm_set1_epi32(937);
|
const __m128i k937 = _mm_set1_epi32(937);
|
||||||
const __m128i k1812 = _mm_set1_epi32(1812);
|
const __m128i k1812 = _mm_set1_epi32(1812);
|
||||||
|
|
||||||
const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8);
|
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 k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8);
|
||||||
const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352,
|
const __m128i k5352_2217p =
|
||||||
2217, 5352, 2217, 5352);
|
_mm_set_epi16(2217, 5352, 2217, 5352, 2217, 5352, 2217, 5352);
|
||||||
const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217,
|
const __m128i k5352_2217m =
|
||||||
-5352, 2217, -5352, 2217);
|
_mm_set_epi16(-5352, 2217, -5352, 2217, -5352, 2217, -5352, 2217);
|
||||||
|
|
||||||
// *in01 = 00 01 10 11 02 03 12 13
|
// *in01 = 00 01 10 11 02 03 12 13
|
||||||
// *in23 = 20 21 30 31 22 23 32 33
|
// *in23 = 20 21 30 31 22 23 32 33
|
||||||
@@ -385,10 +382,10 @@ static void FTransformPass2_SSE2(const __m128i* const v01,
|
|||||||
int16_t* WEBP_RESTRICT out) {
|
int16_t* WEBP_RESTRICT out) {
|
||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
const __m128i seven = _mm_set1_epi16(7);
|
const __m128i seven = _mm_set1_epi16(7);
|
||||||
const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217,
|
const __m128i k5352_2217 =
|
||||||
5352, 2217, 5352, 2217);
|
_mm_set_epi16(5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217);
|
||||||
const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352,
|
const __m128i k2217_5352 =
|
||||||
2217, -5352, 2217, -5352);
|
_mm_set_epi16(2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352);
|
||||||
const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
|
const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
|
||||||
const __m128i k51000 = _mm_set1_epi32(51000);
|
const __m128i k51000 = _mm_set1_epi32(51000);
|
||||||
|
|
||||||
@@ -586,7 +583,7 @@ static void CollectHistogram_SSE2(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
|
const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
|
||||||
int j;
|
int j;
|
||||||
int distribution[MAX_COEFF_THRESH + 1] = { 0 };
|
int distribution[MAX_COEFF_THRESH + 1] = {0};
|
||||||
for (j = start_block; j < end_block; ++j) {
|
for (j = start_block; j < end_block; ++j) {
|
||||||
int16_t out[16];
|
int16_t out[16];
|
||||||
int k;
|
int k;
|
||||||
@@ -927,7 +924,7 @@ static WEBP_INLINE void LD4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
|
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
|
||||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||||
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
|
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(abcdefg));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
||||||
@@ -950,8 +947,8 @@ static WEBP_INLINE void VR4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
|
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
|
||||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||||
const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
|
const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(abcd));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(efgh));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
|
||||||
|
|
||||||
@@ -978,8 +975,8 @@ static WEBP_INLINE void VL4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
|
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
|
||||||
const uint32_t extra_out =
|
const uint32_t extra_out =
|
||||||
(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
|
(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(avg1));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(avg4));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
|
||||||
|
|
||||||
@@ -1000,7 +997,7 @@ static WEBP_INLINE void RD4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
|
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
|
||||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||||
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
|
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
|
||||||
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
|
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(abcdefg));
|
||||||
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
||||||
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
||||||
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
||||||
@@ -1018,8 +1015,7 @@ static WEBP_INLINE void HU4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
|||||||
DST(1, 0) = AVG3(I, J, K);
|
DST(1, 0) = AVG3(I, J, K);
|
||||||
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
|
||||||
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
|
||||||
DST(3, 2) = DST(2, 2) =
|
DST(3, 2) = DST(2, 2) = DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
||||||
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void HD4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
static WEBP_INLINE void HD4_SSE2(uint8_t* WEBP_RESTRICT dst,
|
||||||
@@ -1495,10 +1491,10 @@ static WEBP_INLINE int DoQuantizeBlock_SSE2(
|
|||||||
{
|
{
|
||||||
__m128i outZ0, outZ8;
|
__m128i outZ0, outZ8;
|
||||||
outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0));
|
outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0));
|
||||||
outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0));
|
outZ0 = _mm_shuffle_epi32(outZ0, _MM_SHUFFLE(3, 1, 2, 0));
|
||||||
outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2));
|
outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2));
|
||||||
outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1));
|
outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1));
|
||||||
outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0));
|
outZ8 = _mm_shuffle_epi32(outZ8, _MM_SHUFFLE(3, 1, 2, 0));
|
||||||
outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 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[0], outZ0);
|
||||||
_mm_storeu_si128((__m128i*)&out[8], outZ8);
|
_mm_storeu_si128((__m128i*)&out[8], outZ8);
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#if defined(WEBP_USE_SSE41)
|
#if defined(WEBP_USE_SSE41)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#include <smmintrin.h>
|
#include <smmintrin.h>
|
||||||
|
|
||||||
#include <stdlib.h> // for abs()
|
#include <stdlib.h> // for abs()
|
||||||
|
|
||||||
#include "src/dsp/common_sse2.h"
|
#include "src/dsp/common_sse2.h"
|
||||||
@@ -33,7 +32,7 @@ static void CollectHistogram_SSE41(const uint8_t* WEBP_RESTRICT ref,
|
|||||||
VP8Histogram* WEBP_RESTRICT const histo) {
|
VP8Histogram* WEBP_RESTRICT const histo) {
|
||||||
const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
|
const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
|
||||||
int j;
|
int j;
|
||||||
int distribution[MAX_COEFF_THRESH + 1] = { 0 };
|
int distribution[MAX_COEFF_THRESH + 1] = {0};
|
||||||
for (j = start_block; j < end_block; ++j) {
|
for (j = start_block; j < end_block; ++j) {
|
||||||
int16_t out[16];
|
int16_t out[16];
|
||||||
int k;
|
int k;
|
||||||
@@ -198,7 +197,7 @@ static int Disto16x16_SSE41(const uint8_t* WEBP_RESTRICT const a,
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Generates a pshufb constant for shuffling 16b words.
|
// Generates a pshufb constant for shuffling 16b words.
|
||||||
#define PSHUFB_CST(A,B,C,D,E,F,G,H) \
|
#define PSHUFB_CST(A, B, C, D, E, F, G, H) \
|
||||||
_mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \
|
_mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \
|
||||||
2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \
|
2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \
|
||||||
2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \
|
2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* WEBP_RESTRICT in,
|
|||||||
// leftmost pixel: predict from above.
|
// leftmost pixel: predict from above.
|
||||||
PredictLine_C(in, preds - stride, out, 1);
|
PredictLine_C(in, preds - stride, out, 1);
|
||||||
for (w = 1; w < width; ++w) {
|
for (w = 1; w < width; ++w) {
|
||||||
const int pred = GradientPredictor_C(preds[w - 1],
|
const int pred = GradientPredictor_C(preds[w - 1], preds[w - stride],
|
||||||
preds[w - stride],
|
|
||||||
preds[w - stride - 1]);
|
preds[w - stride - 1]);
|
||||||
out[w] = (uint8_t)(in[w] - pred);
|
out[w] = (uint8_t)(in[w] - pred);
|
||||||
}
|
}
|
||||||
@@ -141,20 +140,20 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* WEBP_RESTRICT in,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if !WEBP_NEON_OMIT_C_CODE
|
#if !WEBP_NEON_OMIT_C_CODE
|
||||||
static void HorizontalFilter_C(const uint8_t* WEBP_RESTRICT data,
|
static void HorizontalFilter_C(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoHorizontalFilter_C(data, width, height, stride, filtered_data);
|
DoHorizontalFilter_C(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VerticalFilter_C(const uint8_t* WEBP_RESTRICT data,
|
static void VerticalFilter_C(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoVerticalFilter_C(data, width, height, stride, filtered_data);
|
DoVerticalFilter_C(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GradientFilter_C(const uint8_t* WEBP_RESTRICT data,
|
static void GradientFilter_C(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoGradientFilter_C(data, width, height, stride, filtered_data);
|
DoGradientFilter_C(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
@@ -162,8 +161,8 @@ static void GradientFilter_C(const uint8_t* WEBP_RESTRICT data,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static void NoneUnfilter_C(const uint8_t* prev, const uint8_t* in,
|
static void NoneUnfilter_C(const uint8_t* prev, const uint8_t* in, uint8_t* out,
|
||||||
uint8_t* out, int width) {
|
int width) {
|
||||||
(void)prev;
|
(void)prev;
|
||||||
if (out != in) memcpy(out, in, width * sizeof(*out));
|
if (out != in) memcpy(out, in, width * sizeof(*out));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
#if defined(WEBP_USE_MIPS_DSP_R2)
|
#if defined(WEBP_USE_MIPS_DSP_R2)
|
||||||
|
|
||||||
#include "src/dsp/dsp.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "src/dsp/dsp.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Helpful macro.
|
// Helpful macro.
|
||||||
|
|
||||||
@@ -34,12 +35,14 @@
|
|||||||
assert(stride >= width); \
|
assert(stride >= width); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \
|
// clang-format off
|
||||||
|
#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) \
|
||||||
|
do { \
|
||||||
const uint8_t* psrc = (uint8_t*)(SRC); \
|
const uint8_t* psrc = (uint8_t*)(SRC); \
|
||||||
uint8_t* pdst = (uint8_t*)(DST); \
|
uint8_t* pdst = (uint8_t*)(DST); \
|
||||||
const int ilength = (int)(LENGTH); \
|
const int ilength = (int)(LENGTH); \
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile( \
|
||||||
".set push \n\t" \
|
".set push \n\t" \
|
||||||
".set noreorder \n\t" \
|
".set noreorder \n\t" \
|
||||||
"srl %[temp0], %[length], 2 \n\t" \
|
"srl %[temp0], %[length], 2 \n\t" \
|
||||||
@@ -101,6 +104,7 @@
|
|||||||
: "memory" \
|
: "memory" \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
||||||
uint8_t* WEBP_RESTRICT dst,
|
uint8_t* WEBP_RESTRICT dst,
|
||||||
@@ -108,13 +112,15 @@ static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
|||||||
DO_PREDICT_LINE(src, dst, length, 0);
|
DO_PREDICT_LINE(src, dst, length, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \
|
// clang-format off
|
||||||
|
#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) \
|
||||||
|
do { \
|
||||||
const uint8_t* psrc = (uint8_t*)(SRC); \
|
const uint8_t* psrc = (uint8_t*)(SRC); \
|
||||||
const uint8_t* ppred = (uint8_t*)(PRED); \
|
const uint8_t* ppred = (uint8_t*)(PRED); \
|
||||||
uint8_t* pdst = (uint8_t*)(DST); \
|
uint8_t* pdst = (uint8_t*)(DST); \
|
||||||
const int ilength = (int)(LENGTH); \
|
const int ilength = (int)(LENGTH); \
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile( \
|
||||||
".set push \n\t" \
|
".set push \n\t" \
|
||||||
".set noreorder \n\t" \
|
".set noreorder \n\t" \
|
||||||
"srl %[temp0], %[length], 0x3 \n\t" \
|
"srl %[temp0], %[length], 0x3 \n\t" \
|
||||||
@@ -167,9 +173,10 @@ static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
|||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST) do { \
|
#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST) \
|
||||||
|
do { \
|
||||||
int temp1, temp2, temp3; \
|
int temp1, temp2, temp3; \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile( \
|
||||||
"lbu %[temp1], 0(%[src]) \n\t" \
|
"lbu %[temp1], 0(%[src]) \n\t" \
|
||||||
"lbu %[temp2], 0(%[pred]) \n\t" \
|
"lbu %[temp2], 0(%[pred]) \n\t" \
|
||||||
"subu %[temp3], %[temp1], %[temp2] \n\t" \
|
"subu %[temp3], %[temp1], %[temp2] \n\t" \
|
||||||
@@ -179,11 +186,13 @@ static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* WEBP_RESTRICT src,
|
|||||||
: "memory" \
|
: "memory" \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Horizontal filter.
|
// Horizontal filter.
|
||||||
|
|
||||||
#define FILTER_LINE_BY_LINE do { \
|
#define FILTER_LINE_BY_LINE \
|
||||||
|
do { \
|
||||||
for (row = 1; row < height; ++row) { \
|
for (row = 1; row < height; ++row) { \
|
||||||
PREDICT_LINE_ONE_PASS(in, preds - stride, out); \
|
PREDICT_LINE_ONE_PASS(in, preds - stride, out); \
|
||||||
DO_PREDICT_LINE(in + 1, out + 1, width - 1, 0); \
|
DO_PREDICT_LINE(in + 1, out + 1, width - 1, 0); \
|
||||||
@@ -221,7 +230,8 @@ static void HorizontalFilter_MIPSdspR2(const uint8_t* WEBP_RESTRICT data,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Vertical filter.
|
// Vertical filter.
|
||||||
|
|
||||||
#define FILTER_LINE_BY_LINE do { \
|
#define FILTER_LINE_BY_LINE \
|
||||||
|
do { \
|
||||||
for (row = 1; row < height; ++row) { \
|
for (row = 1; row < height; ++row) { \
|
||||||
DO_PREDICT_LINE_VERTICAL(in, preds, out, width, 0); \
|
DO_PREDICT_LINE_VERTICAL(in, preds, out, width, 0); \
|
||||||
preds += stride; \
|
preds += stride; \
|
||||||
@@ -260,26 +270,25 @@ static void VerticalFilter_MIPSdspR2(const uint8_t* WEBP_RESTRICT data,
|
|||||||
|
|
||||||
static int GradientPredictor_MIPSdspR2(uint8_t a, uint8_t b, uint8_t c) {
|
static int GradientPredictor_MIPSdspR2(uint8_t a, uint8_t b, uint8_t c) {
|
||||||
int temp0;
|
int temp0;
|
||||||
__asm__ volatile (
|
__asm__ volatile(
|
||||||
"addu %[temp0], %[a], %[b] \n\t"
|
"addu %[temp0], %[a], %[b] \n\t"
|
||||||
"subu %[temp0], %[temp0], %[c] \n\t"
|
"subu %[temp0], %[temp0], %[c] \n\t"
|
||||||
"shll_s.w %[temp0], %[temp0], 23 \n\t"
|
"shll_s.w %[temp0], %[temp0], 23 \n\t"
|
||||||
"precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t"
|
"precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t"
|
||||||
"srl %[temp0], %[temp0], 24 \n\t"
|
"srl %[temp0], %[temp0], 24 \n\t"
|
||||||
: [temp0]"=&r"(temp0)
|
: [temp0] "=&r"(temp0)
|
||||||
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
|
: [a] "r"(a), [b] "r"(b), [c] "r"(c));
|
||||||
);
|
|
||||||
return temp0;
|
return temp0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FILTER_LINE_BY_LINE(PREDS, OPERATION) do { \
|
#define FILTER_LINE_BY_LINE(PREDS, OPERATION) \
|
||||||
|
do { \
|
||||||
for (row = 1; row < height; ++row) { \
|
for (row = 1; row < height; ++row) { \
|
||||||
int w; \
|
int w; \
|
||||||
PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \
|
PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \
|
||||||
for (w = 1; w < width; ++w) { \
|
for (w = 1; w < width; ++w) { \
|
||||||
const int pred = GradientPredictor_MIPSdspR2(PREDS[w - 1], \
|
const int pred = GradientPredictor_MIPSdspR2( \
|
||||||
PREDS[w - stride], \
|
PREDS[w - 1], PREDS[w - stride], PREDS[w - stride - 1]); \
|
||||||
PREDS[w - stride - 1]); \
|
|
||||||
out[w] = in[w] OPERATION pred; \
|
out[w] = in[w] OPERATION pred; \
|
||||||
} \
|
} \
|
||||||
in += stride; \
|
in += stride; \
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
|
|
||||||
#if defined(WEBP_USE_MSA)
|
#if defined(WEBP_USE_MSA)
|
||||||
|
|
||||||
#include "src/dsp/msa_macro.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "src/dsp/msa_macro.h"
|
||||||
|
|
||||||
static WEBP_INLINE void PredictLineInverse0(const uint8_t* src,
|
static WEBP_INLINE void PredictLineInverse0(const uint8_t* src,
|
||||||
const uint8_t* pred,
|
const uint8_t* pred,
|
||||||
uint8_t* WEBP_RESTRICT dst,
|
uint8_t* WEBP_RESTRICT dst,
|
||||||
@@ -70,8 +70,8 @@ static WEBP_INLINE void PredictLineInverse0(const uint8_t* src,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Horrizontal filter
|
// Horrizontal filter
|
||||||
|
|
||||||
static void HorizontalFilter_MSA(const uint8_t* WEBP_RESTRICT data,
|
static void HorizontalFilter_MSA(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
const uint8_t* preds = data;
|
const uint8_t* preds = data;
|
||||||
const uint8_t* in = data;
|
const uint8_t* in = data;
|
||||||
@@ -105,7 +105,7 @@ static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput,
|
|||||||
uint8_t* WEBP_RESTRICT poutput,
|
uint8_t* WEBP_RESTRICT poutput,
|
||||||
int stride, int size) {
|
int stride, int size) {
|
||||||
int w;
|
int w;
|
||||||
const v16i8 zero = { 0 };
|
const v16i8 zero = {0};
|
||||||
while (size >= 16) {
|
while (size >= 16) {
|
||||||
v16u8 pred0, dst0;
|
v16u8 pred0, dst0;
|
||||||
v8i16 a0, a1, b0, b1, c0, c1;
|
v8i16 a0, a1, b0, b1, c0, c1;
|
||||||
@@ -133,9 +133,8 @@ static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GradientFilter_MSA(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
static void GradientFilter_MSA(const uint8_t* WEBP_RESTRICT data,
|
int height, int stride,
|
||||||
int width, int height, int stride,
|
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
const uint8_t* in = data;
|
const uint8_t* in = data;
|
||||||
const uint8_t* preds = data;
|
const uint8_t* preds = data;
|
||||||
@@ -151,7 +150,7 @@ static void GradientFilter_MSA(const uint8_t* WEBP_RESTRICT data,
|
|||||||
out += stride;
|
out += stride;
|
||||||
// Filter line-by-line.
|
// Filter line-by-line.
|
||||||
while (row < height) {
|
while (row < height) {
|
||||||
out[0] = in[0] - preds[- stride];
|
out[0] = in[0] - preds[-stride];
|
||||||
PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1);
|
PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1);
|
||||||
++row;
|
++row;
|
||||||
preds += stride;
|
preds += stride;
|
||||||
@@ -163,8 +162,8 @@ static void GradientFilter_MSA(const uint8_t* WEBP_RESTRICT data,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Vertical filter
|
// Vertical filter
|
||||||
|
|
||||||
static void VerticalFilter_MSA(const uint8_t* WEBP_RESTRICT data,
|
static void VerticalFilter_MSA(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
const uint8_t* in = data;
|
const uint8_t* in = data;
|
||||||
const uint8_t* preds = data;
|
const uint8_t* preds = data;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#if defined(WEBP_USE_NEON)
|
#if defined(WEBP_USE_NEON)
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "src/dsp/neon.h"
|
#include "src/dsp/neon.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -66,8 +67,9 @@ static void PredictLineLeft_NEON(const uint8_t* WEBP_RESTRICT src,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Horizontal filter.
|
// Horizontal filter.
|
||||||
|
|
||||||
static WEBP_INLINE void DoHorizontalFilter_NEON(
|
static WEBP_INLINE void DoHorizontalFilter_NEON(const uint8_t* WEBP_RESTRICT in,
|
||||||
const uint8_t* WEBP_RESTRICT in, int width, int height, int stride,
|
int width, int height,
|
||||||
|
int stride,
|
||||||
uint8_t* WEBP_RESTRICT out) {
|
uint8_t* WEBP_RESTRICT out) {
|
||||||
int row;
|
int row;
|
||||||
DCHECK(in, out);
|
DCHECK(in, out);
|
||||||
@@ -88,8 +90,8 @@ static WEBP_INLINE void DoHorizontalFilter_NEON(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HorizontalFilter_NEON(const uint8_t* WEBP_RESTRICT data,
|
static void HorizontalFilter_NEON(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoHorizontalFilter_NEON(data, width, height, stride, filtered_data);
|
DoHorizontalFilter_NEON(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
@@ -118,8 +120,8 @@ static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* WEBP_RESTRICT in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VerticalFilter_NEON(const uint8_t* WEBP_RESTRICT data,
|
static void VerticalFilter_NEON(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoVerticalFilter_NEON(data, width, height, stride, filtered_data);
|
DoVerticalFilter_NEON(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
@@ -172,8 +174,8 @@ static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* WEBP_RESTRICT in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GradientFilter_NEON(const uint8_t* WEBP_RESTRICT data,
|
static void GradientFilter_NEON(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoGradientFilter_NEON(data, width, height, stride, filtered_data);
|
DoGradientFilter_NEON(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
@@ -233,13 +235,14 @@ static void VerticalUnfilter_NEON(const uint8_t* prev, const uint8_t* in,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (USE_GRADIENT_UNFILTER == 1)
|
#if (USE_GRADIENT_UNFILTER == 1)
|
||||||
#define GRAD_PROCESS_LANE(L) do { \
|
#define GRAD_PROCESS_LANE(L) \
|
||||||
|
do { \
|
||||||
const uint8x8_t tmp1 = ROTATE_RIGHT_N(pred, 1); /* rotate predictor in */ \
|
const uint8x8_t tmp1 = ROTATE_RIGHT_N(pred, 1); /* rotate predictor in */ \
|
||||||
const int16x8_t tmp2 = vaddq_s16(BC, U8_TO_S16(tmp1)); \
|
const int16x8_t tmp2 = vaddq_s16(BC, U8_TO_S16(tmp1)); \
|
||||||
const uint8x8_t delta = vqmovun_s16(tmp2); \
|
const uint8x8_t delta = vqmovun_s16(tmp2); \
|
||||||
pred = vadd_u8(D, delta); \
|
pred = vadd_u8(D, delta); \
|
||||||
out = vext_u8(out, ROTATE_LEFT_N(pred, (L)), 1); \
|
out = vext_u8(out, ROTATE_LEFT_N(pred, (L)), 1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void GradientPredictInverse_NEON(const uint8_t* const in,
|
static void GradientPredictInverse_NEON(const uint8_t* const in,
|
||||||
const uint8_t* const top,
|
const uint8_t* const top,
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ static void PredictLineLeft_SSE2(const uint8_t* WEBP_RESTRICT src,
|
|||||||
const int max_pos = length & ~31;
|
const int max_pos = length & ~31;
|
||||||
assert(length >= 0);
|
assert(length >= 0);
|
||||||
for (i = 0; i < max_pos; i += 32) {
|
for (i = 0; i < max_pos; i += 32) {
|
||||||
const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 ));
|
const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0));
|
||||||
const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1));
|
const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1));
|
||||||
const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 ));
|
const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16));
|
||||||
const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1));
|
const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1));
|
||||||
const __m128i C0 = _mm_sub_epi8(A0, B0);
|
const __m128i C0 = _mm_sub_epi8(A0, B0);
|
||||||
const __m128i C1 = _mm_sub_epi8(A1, B1);
|
const __m128i C1 = _mm_sub_epi8(A1, B1);
|
||||||
@@ -77,8 +77,9 @@ static void PredictLineLeft_SSE2(const uint8_t* WEBP_RESTRICT src,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Horizontal filter.
|
// Horizontal filter.
|
||||||
|
|
||||||
static WEBP_INLINE void DoHorizontalFilter_SSE2(
|
static WEBP_INLINE void DoHorizontalFilter_SSE2(const uint8_t* WEBP_RESTRICT in,
|
||||||
const uint8_t* WEBP_RESTRICT in, int width, int height, int stride,
|
int width, int height,
|
||||||
|
int stride,
|
||||||
uint8_t* WEBP_RESTRICT out) {
|
uint8_t* WEBP_RESTRICT out) {
|
||||||
int row;
|
int row;
|
||||||
DCHECK(in, out);
|
DCHECK(in, out);
|
||||||
@@ -183,20 +184,20 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* WEBP_RESTRICT in,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static void HorizontalFilter_SSE2(const uint8_t* WEBP_RESTRICT data,
|
static void HorizontalFilter_SSE2(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoHorizontalFilter_SSE2(data, width, height, stride, filtered_data);
|
DoHorizontalFilter_SSE2(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VerticalFilter_SSE2(const uint8_t* WEBP_RESTRICT data,
|
static void VerticalFilter_SSE2(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoVerticalFilter_SSE2(data, width, height, stride, filtered_data);
|
DoVerticalFilter_SSE2(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GradientFilter_SSE2(const uint8_t* WEBP_RESTRICT data,
|
static void GradientFilter_SSE2(const uint8_t* WEBP_RESTRICT data, int width,
|
||||||
int width, int height, int stride,
|
int height, int stride,
|
||||||
uint8_t* WEBP_RESTRICT filtered_data) {
|
uint8_t* WEBP_RESTRICT filtered_data) {
|
||||||
DoGradientFilter_SSE2(data, width, height, stride, filtered_data);
|
DoGradientFilter_SSE2(data, width, height, stride, filtered_data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
|
|||||||
return Average2(Average2(a0, a2), a1);
|
return Average2(Average2(a0, a2), a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
|
static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, uint32_t a2,
|
||||||
uint32_t a2, uint32_t a3) {
|
uint32_t a3) {
|
||||||
return Average2(Average2(a0, a1), Average2(a2, a3));
|
return Average2(Average2(a0, a1), Average2(a2, a3));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,11 +61,9 @@ static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
|
|||||||
static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
|
static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
|
||||||
uint32_t c2) {
|
uint32_t c2) {
|
||||||
const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
|
const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
|
||||||
const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
|
const int r = AddSubtractComponentFull((c0 >> 16) & 0xff, (c1 >> 16) & 0xff,
|
||||||
(c1 >> 16) & 0xff,
|
|
||||||
(c2 >> 16) & 0xff);
|
(c2 >> 16) & 0xff);
|
||||||
const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
|
const int g = AddSubtractComponentFull((c0 >> 8) & 0xff, (c1 >> 8) & 0xff,
|
||||||
(c1 >> 8) & 0xff,
|
|
||||||
(c2 >> 8) & 0xff);
|
(c2 >> 8) & 0xff);
|
||||||
const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
|
const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
|
||||||
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
|
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
|
||||||
@@ -88,9 +86,9 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
|
|||||||
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
|
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
|
||||||
// inlined.
|
// inlined.
|
||||||
#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
|
#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
|
||||||
# define LOCAL_INLINE __attribute__ ((noinline))
|
#define LOCAL_INLINE __attribute__((noinline))
|
||||||
#else
|
#else
|
||||||
# define LOCAL_INLINE WEBP_INLINE
|
#define LOCAL_INLINE WEBP_INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static LOCAL_INLINE int Sub3(int a, int b, int c) {
|
static LOCAL_INLINE int Sub3(int a, int b, int c) {
|
||||||
@@ -103,10 +101,10 @@ static LOCAL_INLINE int Sub3(int a, int b, int c) {
|
|||||||
|
|
||||||
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
|
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
|
||||||
const int pa_minus_pb =
|
const int pa_minus_pb =
|
||||||
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
|
Sub3((a >> 24), (b >> 24), (c >> 24)) +
|
||||||
Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
|
Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
|
||||||
Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
|
Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
|
||||||
Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff);
|
Sub3((a) & 0xff, (b) & 0xff, (c) & 0xff);
|
||||||
return (pa_minus_pb <= 0) ? a : b;
|
return (pa_minus_pb <= 0) ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,8 +275,7 @@ void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int ColorTransformDelta(int8_t color_pred,
|
static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) {
|
||||||
int8_t color) {
|
|
||||||
return ((int)color_pred * color) >> 5;
|
return ((int)color_pred * color) >> 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +321,7 @@ static void ColorSpaceInverseTransform_C(const VP8LTransform* const transform,
|
|||||||
|
|
||||||
while (y < y_end) {
|
while (y < y_end) {
|
||||||
const uint32_t* pred = pred_row;
|
const uint32_t* pred = pred_row;
|
||||||
VP8LMultipliers m = { 0, 0, 0 };
|
VP8LMultipliers m = {0, 0, 0};
|
||||||
const uint32_t* const src_safe_end = src + safe_width;
|
const uint32_t* const src_safe_end = src + safe_width;
|
||||||
const uint32_t* const src_end = src + width;
|
const uint32_t* const src_end = src + width;
|
||||||
while (src < src_safe_end) {
|
while (src < src_safe_end) {
|
||||||
@@ -346,6 +343,7 @@ static void ColorSpaceInverseTransform_C(const VP8LTransform* const transform,
|
|||||||
|
|
||||||
// Separate out pixels packed together using pixel-bundling.
|
// Separate out pixels packed together using pixel-bundling.
|
||||||
// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t).
|
// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t).
|
||||||
|
// clang-format off
|
||||||
#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \
|
#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \
|
||||||
GET_INDEX, GET_VALUE) \
|
GET_INDEX, GET_VALUE) \
|
||||||
static void F_NAME(const TYPE* src, const uint32_t* const color_map, \
|
static void F_NAME(const TYPE* src, const uint32_t* const color_map, \
|
||||||
@@ -386,17 +384,18 @@ STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \
|
|||||||
VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \
|
VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
COLOR_INDEX_INVERSE(ColorIndexInverseTransform_C, MapARGB_C, static,
|
COLOR_INDEX_INVERSE(ColorIndexInverseTransform_C, MapARGB_C, static, uint32_t,
|
||||||
uint32_t, 32b, VP8GetARGBIndex, VP8GetARGBValue)
|
32b, VP8GetARGBIndex, VP8GetARGBValue)
|
||||||
COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha_C, ,
|
COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha_C, , uint8_t,
|
||||||
uint8_t, 8b, VP8GetAlphaIndex, VP8GetAlphaValue)
|
8b, VP8GetAlphaIndex, VP8GetAlphaValue)
|
||||||
|
|
||||||
#undef COLOR_INDEX_INVERSE
|
#undef COLOR_INDEX_INVERSE
|
||||||
|
|
||||||
void VP8LInverseTransform(const VP8LTransform* const transform,
|
void VP8LInverseTransform(const VP8LTransform* const transform, int row_start,
|
||||||
int row_start, int row_end,
|
int row_end, const uint32_t* const in,
|
||||||
const uint32_t* const in, uint32_t* const out) {
|
uint32_t* const out) {
|
||||||
const int width = transform->xsize;
|
const int width = transform->xsize;
|
||||||
assert(row_start < row_end);
|
assert(row_start < row_end);
|
||||||
assert(row_end <= transform->ysize);
|
assert(row_end <= transform->ysize);
|
||||||
@@ -424,7 +423,8 @@ void VP8LInverseTransform(const VP8LTransform* const transform,
|
|||||||
// the effective width of VP8LSubSampleSize(xsize, bits). All other
|
// the effective width of VP8LSubSampleSize(xsize, bits). All other
|
||||||
// transforms work on effective width of 'xsize'.
|
// transforms work on effective width of 'xsize'.
|
||||||
const int out_stride = (row_end - row_start) * width;
|
const int out_stride = (row_end - row_start) * width;
|
||||||
const int in_stride = (row_end - row_start) *
|
const int in_stride =
|
||||||
|
(row_end - row_start) *
|
||||||
VP8LSubSampleSize(transform->xsize, transform->bits);
|
VP8LSubSampleSize(transform->xsize, transform->bits);
|
||||||
uint32_t* const src = out + out_stride - in_stride;
|
uint32_t* const src = out + out_stride - in_stride;
|
||||||
memmove(src, out, in_stride * sizeof(*src));
|
memmove(src, out, in_stride * sizeof(*src));
|
||||||
@@ -443,12 +443,12 @@ static int is_big_endian(void) {
|
|||||||
static const union {
|
static const union {
|
||||||
uint16_t w;
|
uint16_t w;
|
||||||
uint8_t b[2];
|
uint8_t b[2];
|
||||||
} tmp = { 1 };
|
} tmp = {1};
|
||||||
return (tmp.b[0] != 1);
|
return (tmp.b[0] != 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LConvertBGRAToRGB_C(const uint32_t* WEBP_RESTRICT src,
|
void VP8LConvertBGRAToRGB_C(const uint32_t* WEBP_RESTRICT src, int num_pixels,
|
||||||
int num_pixels, uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
const uint32_t* const src_end = src + num_pixels;
|
const uint32_t* const src_end = src + num_pixels;
|
||||||
while (src < src_end) {
|
while (src < src_end) {
|
||||||
const uint32_t argb = *src++;
|
const uint32_t argb = *src++;
|
||||||
@@ -458,8 +458,8 @@ void VP8LConvertBGRAToRGB_C(const uint32_t* WEBP_RESTRICT src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LConvertBGRAToRGBA_C(const uint32_t* WEBP_RESTRICT src,
|
void VP8LConvertBGRAToRGBA_C(const uint32_t* WEBP_RESTRICT src, int num_pixels,
|
||||||
int num_pixels, uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
const uint32_t* const src_end = src + num_pixels;
|
const uint32_t* const src_end = src + num_pixels;
|
||||||
while (src < src_end) {
|
while (src < src_end) {
|
||||||
const uint32_t argb = *src++;
|
const uint32_t argb = *src++;
|
||||||
@@ -504,8 +504,8 @@ void VP8LConvertBGRAToRGB565_C(const uint32_t* WEBP_RESTRICT src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LConvertBGRAToBGR_C(const uint32_t* WEBP_RESTRICT src,
|
void VP8LConvertBGRAToBGR_C(const uint32_t* WEBP_RESTRICT src, int num_pixels,
|
||||||
int num_pixels, uint8_t* WEBP_RESTRICT dst) {
|
uint8_t* WEBP_RESTRICT dst) {
|
||||||
const uint32_t* const src_end = src + num_pixels;
|
const uint32_t* const src_end = src + num_pixels;
|
||||||
while (src < src_end) {
|
while (src < src_end) {
|
||||||
const uint32_t argb = *src++;
|
const uint32_t argb = *src++;
|
||||||
@@ -607,7 +607,8 @@ extern void VP8LDspInitNEON(void);
|
|||||||
extern void VP8LDspInitMIPSdspR2(void);
|
extern void VP8LDspInitMIPSdspR2(void);
|
||||||
extern void VP8LDspInitMSA(void);
|
extern void VP8LDspInitMSA(void);
|
||||||
|
|
||||||
#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \
|
#define COPY_PREDICTOR_ARRAY(IN, OUT) \
|
||||||
|
do { \
|
||||||
(OUT)[0] = IN##0_C; \
|
(OUT)[0] = IN##0_C; \
|
||||||
(OUT)[1] = IN##1_C; \
|
(OUT)[1] = IN##1_C; \
|
||||||
(OUT)[2] = IN##2_C; \
|
(OUT)[2] = IN##2_C; \
|
||||||
@@ -624,7 +625,7 @@ extern void VP8LDspInitMSA(void);
|
|||||||
(OUT)[13] = IN##13_C; \
|
(OUT)[13] = IN##13_C; \
|
||||||
(OUT)[14] = IN##0_C; /* <- padding security sentinels*/ \
|
(OUT)[14] = IN##0_C; /* <- padding security sentinels*/ \
|
||||||
(OUT)[15] = IN##0_C; \
|
(OUT)[15] = IN##0_C; \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
WEBP_DSP_INIT_FUNC(VP8LDspInit) {
|
WEBP_DSP_INIT_FUNC(VP8LDspInit) {
|
||||||
COPY_PREDICTOR_ARRAY(VP8LPredictor, VP8LPredictors)
|
COPY_PREDICTOR_ARRAY(VP8LPredictor, VP8LPredictors)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
#define WEBP_DSP_LOSSLESS_H_
|
#define WEBP_DSP_LOSSLESS_H_
|
||||||
|
|
||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
#include "src/webp/types.h"
|
|
||||||
#include "src/webp/decode.h"
|
#include "src/webp/decode.h"
|
||||||
|
#include "src/webp/types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -88,8 +88,8 @@ struct VP8LTransform; // Defined in dec/vp8li.h.
|
|||||||
// The *in and *out pointers refer to source and destination data respectively
|
// The *in and *out pointers refer to source and destination data respectively
|
||||||
// corresponding to the intermediate row (row_start).
|
// corresponding to the intermediate row (row_start).
|
||||||
void VP8LInverseTransform(const struct VP8LTransform* const transform,
|
void VP8LInverseTransform(const struct VP8LTransform* const transform,
|
||||||
int row_start, int row_end,
|
int row_start, int row_end, const uint32_t* const in,
|
||||||
const uint32_t* const in, uint32_t* const out);
|
uint32_t* const out);
|
||||||
|
|
||||||
// Color space conversion.
|
// Color space conversion.
|
||||||
typedef void (*VP8LConvertFunc)(const uint32_t* WEBP_RESTRICT src,
|
typedef void (*VP8LConvertFunc)(const uint32_t* WEBP_RESTRICT src,
|
||||||
@@ -107,13 +107,11 @@ void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
|
|||||||
WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
|
WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
|
||||||
|
|
||||||
typedef void (*VP8LMapARGBFunc)(const uint32_t* src,
|
typedef void (*VP8LMapARGBFunc)(const uint32_t* src,
|
||||||
const uint32_t* const color_map,
|
const uint32_t* const color_map, uint32_t* dst,
|
||||||
uint32_t* dst, int y_start,
|
int y_start, int y_end, int width);
|
||||||
int y_end, int width);
|
|
||||||
typedef void (*VP8LMapAlphaFunc)(const uint8_t* src,
|
typedef void (*VP8LMapAlphaFunc)(const uint8_t* src,
|
||||||
const uint32_t* const color_map,
|
const uint32_t* const color_map, uint8_t* dst,
|
||||||
uint8_t* dst, int y_start,
|
int y_start, int y_end, int width);
|
||||||
int y_end, int width);
|
|
||||||
|
|
||||||
extern VP8LMapARGBFunc VP8LMapColor32b;
|
extern VP8LMapARGBFunc VP8LMapColor32b;
|
||||||
extern VP8LMapAlphaFunc VP8LMapColor8b;
|
extern VP8LMapAlphaFunc VP8LMapColor8b;
|
||||||
@@ -158,16 +156,14 @@ typedef void (*VP8LTransformColorFunc)(
|
|||||||
extern VP8LTransformColorFunc VP8LTransformColor;
|
extern VP8LTransformColorFunc VP8LTransformColor;
|
||||||
extern VP8LTransformColorFunc VP8LTransformColor_SSE;
|
extern VP8LTransformColorFunc VP8LTransformColor_SSE;
|
||||||
typedef void (*VP8LCollectColorBlueTransformsFunc)(
|
typedef void (*VP8LCollectColorBlueTransformsFunc)(
|
||||||
const uint32_t* WEBP_RESTRICT argb, int stride,
|
const uint32_t* WEBP_RESTRICT argb, int stride, int tile_width,
|
||||||
int tile_width, int tile_height,
|
int tile_height, int green_to_blue, int red_to_blue, uint32_t histo[]);
|
||||||
int green_to_blue, int red_to_blue, uint32_t histo[]);
|
|
||||||
extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;
|
extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;
|
||||||
extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms_SSE;
|
extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms_SSE;
|
||||||
|
|
||||||
typedef void (*VP8LCollectColorRedTransformsFunc)(
|
typedef void (*VP8LCollectColorRedTransformsFunc)(
|
||||||
const uint32_t* WEBP_RESTRICT argb, int stride,
|
const uint32_t* WEBP_RESTRICT argb, int stride, int tile_width,
|
||||||
int tile_width, int tile_height,
|
int tile_height, int green_to_red, uint32_t histo[]);
|
||||||
int green_to_red, uint32_t histo[]);
|
|
||||||
extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;
|
extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;
|
||||||
extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms_SSE;
|
extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms_SSE;
|
||||||
|
|
||||||
@@ -176,14 +172,13 @@ void VP8LTransformColor_C(const VP8LMultipliers* WEBP_RESTRICT const m,
|
|||||||
uint32_t* WEBP_RESTRICT data, int num_pixels);
|
uint32_t* WEBP_RESTRICT data, int num_pixels);
|
||||||
void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels);
|
void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels);
|
||||||
void VP8LCollectColorRedTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
void VP8LCollectColorRedTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
||||||
int stride,
|
int stride, int tile_width,
|
||||||
int tile_width, int tile_height,
|
int tile_height, int green_to_red,
|
||||||
int green_to_red, uint32_t histo[]);
|
|
||||||
void VP8LCollectColorBlueTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
|
||||||
int stride,
|
|
||||||
int tile_width, int tile_height,
|
|
||||||
int green_to_blue, int red_to_blue,
|
|
||||||
uint32_t histo[]);
|
uint32_t histo[]);
|
||||||
|
void VP8LCollectColorBlueTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
||||||
|
int stride, int tile_width,
|
||||||
|
int tile_height, int green_to_blue,
|
||||||
|
int red_to_blue, uint32_t histo[]);
|
||||||
|
|
||||||
extern VP8LPredictorAddSubFunc VP8LPredictorsSub[16];
|
extern VP8LPredictorAddSubFunc VP8LPredictorsSub[16];
|
||||||
extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16];
|
extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16];
|
||||||
@@ -256,8 +251,8 @@ typedef void (*VP8LBundleColorMapFunc)(const uint8_t* WEBP_RESTRICT const row,
|
|||||||
uint32_t* WEBP_RESTRICT dst);
|
uint32_t* WEBP_RESTRICT dst);
|
||||||
extern VP8LBundleColorMapFunc VP8LBundleColorMap;
|
extern VP8LBundleColorMapFunc VP8LBundleColorMap;
|
||||||
extern VP8LBundleColorMapFunc VP8LBundleColorMap_SSE;
|
extern VP8LBundleColorMapFunc VP8LBundleColorMap_SSE;
|
||||||
void VP8LBundleColorMap_C(const uint8_t* WEBP_RESTRICT const row,
|
void VP8LBundleColorMap_C(const uint8_t* WEBP_RESTRICT const row, int width,
|
||||||
int width, int xbits, uint32_t* WEBP_RESTRICT dst);
|
int xbits, uint32_t* WEBP_RESTRICT dst);
|
||||||
|
|
||||||
// Must be called before calling any of the above methods.
|
// Must be called before calling any of the above methods.
|
||||||
void VP8LEncDspInit(void);
|
void VP8LEncDspInit(void);
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
#if defined(WEBP_USE_AVX2)
|
#if defined(WEBP_USE_AVX2)
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
#include "src/dsp/lossless.h"
|
#include "src/dsp/lossless.h"
|
||||||
@@ -362,9 +362,8 @@ static void TransformColorInverse_AVX2(const VP8LMultipliers* const m,
|
|||||||
int num_pixels, uint32_t* dst) {
|
int num_pixels, uint32_t* dst) {
|
||||||
// sign-extended multiplying constants, pre-shifted by 5.
|
// sign-extended multiplying constants, pre-shifted by 5.
|
||||||
#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
|
#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
|
||||||
const __m256i mults_rb =
|
const __m256i mults_rb = _mm256_set1_epi32(
|
||||||
_mm256_set1_epi32((int)((uint32_t)CST(green_to_red) << 16 |
|
(int)((uint32_t)CST(green_to_red) << 16 | (CST(green_to_blue) & 0xffff)));
|
||||||
(CST(green_to_blue) & 0xffff)));
|
|
||||||
const __m256i mults_b2 = _mm256_set1_epi32(CST(red_to_blue));
|
const __m256i mults_b2 = _mm256_set1_epi32(CST(red_to_blue));
|
||||||
#undef CST
|
#undef CST
|
||||||
const __m256i mask_ag = _mm256_set1_epi32((int)0xff00ff00);
|
const __m256i mask_ag = _mm256_set1_epi32((int)0xff00ff00);
|
||||||
|
|||||||
@@ -35,13 +35,9 @@ static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) {
|
|||||||
return (idx >> 8) & 0xff;
|
return (idx >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) {
|
static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { return idx; }
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) {
|
static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { return val; }
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) {
|
static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) {
|
||||||
return (val >> 8) & 0xff;
|
return (val >> 8) & 0xff;
|
||||||
@@ -172,16 +168,16 @@ static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sum of each component, mod 256.
|
// Sum of each component, mod 256.
|
||||||
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
|
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE uint32_t
|
||||||
uint32_t VP8LAddPixels(uint32_t a, uint32_t b) {
|
VP8LAddPixels(uint32_t a, uint32_t b) {
|
||||||
const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u);
|
const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u);
|
||||||
const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu);
|
const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu);
|
||||||
return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
|
return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Difference of each component, mod 256.
|
// Difference of each component, mod 256.
|
||||||
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
|
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE uint32_t
|
||||||
uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
|
VP8LSubPixels(uint32_t a, uint32_t b) {
|
||||||
const uint32_t alpha_and_green =
|
const uint32_t alpha_and_green =
|
||||||
0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
|
0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
|
||||||
const uint32_t red_and_blue =
|
const uint32_t red_and_blue =
|
||||||
@@ -198,7 +194,7 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
|
|||||||
// The predictor is added to the output pixel (which
|
// The predictor is added to the output pixel (which
|
||||||
// is therefore considered as a residual) to get the final prediction.
|
// is therefore considered as a residual) to get the final prediction.
|
||||||
#define GENERATE_PREDICTOR_ADD(PREDICTOR, PREDICTOR_ADD) \
|
#define GENERATE_PREDICTOR_ADD(PREDICTOR, PREDICTOR_ADD) \
|
||||||
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
|
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
|
||||||
int num_pixels, uint32_t* WEBP_RESTRICT out) { \
|
int num_pixels, uint32_t* WEBP_RESTRICT out) { \
|
||||||
int x; \
|
int x; \
|
||||||
assert(upper != NULL); \
|
assert(upper != NULL); \
|
||||||
@@ -206,7 +202,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
|
|||||||
const uint32_t pred = (PREDICTOR)(&out[x - 1], upper + x); \
|
const uint32_t pred = (PREDICTOR)(&out[x - 1], upper + x); \
|
||||||
out[x] = VP8LAddPixels(in[x], pred); \
|
out[x] = VP8LAddPixels(in[x], pred); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -69,8 +69,7 @@ const uint32_t kLog2Table[LOG_LOOKUP_IDX_MAX] = {
|
|||||||
65865245, 65917522, 65969575, 66021404, 66073013, 66124403, 66175575,
|
65865245, 65917522, 65969575, 66021404, 66073013, 66124403, 66175575,
|
||||||
66226531, 66277275, 66327806, 66378127, 66428240, 66478146, 66527847,
|
66226531, 66277275, 66327806, 66378127, 66428240, 66478146, 66527847,
|
||||||
66577345, 66626641, 66675737, 66724635, 66773336, 66821842, 66870154,
|
66577345, 66626641, 66675737, 66724635, 66773336, 66821842, 66870154,
|
||||||
66918274, 66966204, 67013944, 67061497
|
66918274, 66966204, 67013944, 67061497};
|
||||||
};
|
|
||||||
|
|
||||||
// lookup table for small values of int*log2(int) * (1 << LOG_2_PRECISION_BITS).
|
// lookup table for small values of int*log2(int) * (1 << LOG_2_PRECISION_BITS).
|
||||||
// Obtained in Python with:
|
// Obtained in Python with:
|
||||||
@@ -80,18 +79,18 @@ const uint32_t kLog2Table[LOG_LOOKUP_IDX_MAX] = {
|
|||||||
// print(',\n '.join([','.join(v) for v in batched([i.rjust(15)
|
// print(',\n '.join([','.join(v) for v in batched([i.rjust(15)
|
||||||
// for i in a],4)]))
|
// for i in a],4)]))
|
||||||
const uint64_t kSLog2Table[LOG_LOOKUP_IDX_MAX] = {
|
const uint64_t kSLog2Table[LOG_LOOKUP_IDX_MAX] = {
|
||||||
0, 0, 16777216, 39886887,
|
0ull, 0ull, 16777216ull, 39886887ull,
|
||||||
67108864, 97388723, 130105423, 164848600,
|
67108864ull, 97388723ull, 130105423ull, 164848600ull,
|
||||||
201326592, 239321324, 278663526, 319217973,
|
201326592ull, 239321324ull, 278663526ull, 319217973ull,
|
||||||
360874141, 403539997, 447137711, 491600606,
|
360874141ull, 403539997ull, 447137711ull, 491600606ull,
|
||||||
536870912, 582898099, 629637592, 677049776,
|
536870912ull, 582898099ull, 629637592ull, 677049776ull,
|
||||||
725099212, 773754010, 822985323, 872766924,
|
725099212ull, 773754010ull, 822985323ull, 872766924ull,
|
||||||
923074875, 973887230, 1025183802, 1076945958,
|
923074875ull, 973887230ull, 1025183802ull, 1076945958ull,
|
||||||
1129156447, 1181799249, 1234859451, 1288323135,
|
1129156447ull, 1181799249ull, 1234859451ull, 1288323135ull,
|
||||||
1342177280, 1396409681, 1451008871, 1505964059,
|
1342177280ull, 1396409681ull, 1451008871ull, 1505964059ull,
|
||||||
1561265072, 1616902301, 1672866655, 1729149526,
|
1561265072ull, 1616902301ull, 1672866655ull, 1729149526ull,
|
||||||
1785742744, 1842638548, 1899829557, 1957308741,
|
1785742744ull, 1842638548ull, 1899829557ull, 1957308741ull,
|
||||||
2015069397, 2073105127, 2131409817, 2189977618ull,
|
2015069397ull, 2073105127ull, 2131409817ull, 2189977618ull,
|
||||||
2248802933ull, 2307880396ull, 2367204859ull, 2426771383ull,
|
2248802933ull, 2307880396ull, 2367204859ull, 2426771383ull,
|
||||||
2486575220ull, 2546611805ull, 2606876748ull, 2667365819ull,
|
2486575220ull, 2546611805ull, 2606876748ull, 2667365819ull,
|
||||||
2728074942ull, 2789000187ull, 2850137762ull, 2911484006ull,
|
2728074942ull, 2789000187ull, 2850137762ull, 2911484006ull,
|
||||||
@@ -143,15 +142,14 @@ const uint64_t kSLog2Table[LOG_LOOKUP_IDX_MAX] = {
|
|||||||
15918673369ull, 15997128556ull, 16075633960ull, 16154189373ull,
|
15918673369ull, 15997128556ull, 16075633960ull, 16154189373ull,
|
||||||
16232794589ull, 16311449405ull, 16390153617ull, 16468907026ull,
|
16232794589ull, 16311449405ull, 16390153617ull, 16468907026ull,
|
||||||
16547709431ull, 16626560636ull, 16705460444ull, 16784408661ull,
|
16547709431ull, 16626560636ull, 16705460444ull, 16784408661ull,
|
||||||
16863405094ull, 16942449552ull, 17021541845ull, 17100681785ull
|
16863405094ull, 16942449552ull, 17021541845ull, 17100681785ull};
|
||||||
};
|
|
||||||
|
|
||||||
const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {
|
const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {
|
||||||
{ 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1},
|
{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},
|
{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},
|
{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},
|
{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},
|
{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}, {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},
|
{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}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
|
||||||
@@ -214,40 +212,41 @@ const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = {
|
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, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
|
2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
|
||||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
||||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
||||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
|
||||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
|
||||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
|
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
|
||||||
127,
|
103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 0, 1, 2, 3, 4,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
||||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
||||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
|
||||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126
|
95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||||
};
|
110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
|
||||||
|
125, 126};
|
||||||
|
|
||||||
static uint64_t FastSLog2Slow_C(uint32_t v) {
|
static uint64_t FastSLog2Slow_C(uint32_t v) {
|
||||||
assert(v >= LOG_LOOKUP_IDX_MAX);
|
assert(v >= LOG_LOOKUP_IDX_MAX);
|
||||||
@@ -469,9 +468,7 @@ static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) {
|
|||||||
return ((int)color_pred * color) >> 5;
|
return ((int)color_pred * color) >> 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int8_t U32ToS8(uint32_t v) {
|
static WEBP_INLINE int8_t U32ToS8(uint32_t v) { return (int8_t)(v & 0xff); }
|
||||||
return (int8_t)(v & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VP8LTransformColor_C(const VP8LMultipliers* WEBP_RESTRICT const m,
|
void VP8LTransformColor_C(const VP8LMultipliers* WEBP_RESTRICT const m,
|
||||||
uint32_t* WEBP_RESTRICT data, int num_pixels) {
|
uint32_t* WEBP_RESTRICT data, int num_pixels) {
|
||||||
@@ -511,9 +508,9 @@ static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VP8LCollectColorRedTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
void VP8LCollectColorRedTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
||||||
int stride,
|
int stride, int tile_width,
|
||||||
int tile_width, int tile_height,
|
int tile_height, int green_to_red,
|
||||||
int green_to_red, uint32_t histo[]) {
|
uint32_t histo[]) {
|
||||||
while (tile_height-- > 0) {
|
while (tile_height-- > 0) {
|
||||||
int x;
|
int x;
|
||||||
for (x = 0; x < tile_width; ++x) {
|
for (x = 0; x < tile_width; ++x) {
|
||||||
@@ -524,10 +521,9 @@ void VP8LCollectColorRedTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VP8LCollectColorBlueTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
void VP8LCollectColorBlueTransforms_C(const uint32_t* WEBP_RESTRICT argb,
|
||||||
int stride,
|
int stride, int tile_width,
|
||||||
int tile_width, int tile_height,
|
int tile_height, int green_to_blue,
|
||||||
int green_to_blue, int red_to_blue,
|
int red_to_blue, uint32_t histo[]) {
|
||||||
uint32_t histo[]) {
|
|
||||||
while (tile_height-- > 0) {
|
while (tile_height-- > 0) {
|
||||||
int x;
|
int x;
|
||||||
for (x = 0; x < tile_width; ++x) {
|
for (x = 0; x < tile_width; ++x) {
|
||||||
@@ -551,8 +547,8 @@ static int VectorMismatch_C(const uint32_t* const array1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
|
// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
|
||||||
void VP8LBundleColorMap_C(const uint8_t* WEBP_RESTRICT const row,
|
void VP8LBundleColorMap_C(const uint8_t* WEBP_RESTRICT const row, int width,
|
||||||
int width, int xbits, uint32_t* WEBP_RESTRICT dst) {
|
int xbits, uint32_t* WEBP_RESTRICT dst) {
|
||||||
int x;
|
int x;
|
||||||
if (xbits > 0) {
|
if (xbits > 0) {
|
||||||
const int bit_depth = 1 << (3 - xbits);
|
const int bit_depth = 1 << (3 - xbits);
|
||||||
@@ -618,9 +614,8 @@ static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper,
|
|||||||
// It subtracts the prediction from the input pixel and stores the residual
|
// It subtracts the prediction from the input pixel and stores the residual
|
||||||
// in the output pixel.
|
// in the output pixel.
|
||||||
#define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \
|
#define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \
|
||||||
static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \
|
static void PredictorSub##PREDICTOR_I##_C( \
|
||||||
const uint32_t* upper, \
|
const uint32_t* in, const uint32_t* upper, int num_pixels, \
|
||||||
int num_pixels, \
|
|
||||||
uint32_t* WEBP_RESTRICT out) { \
|
uint32_t* WEBP_RESTRICT out) { \
|
||||||
int x; \
|
int x; \
|
||||||
assert(upper != NULL); \
|
assert(upper != NULL); \
|
||||||
@@ -629,7 +624,7 @@ static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \
|
|||||||
VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \
|
VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \
|
||||||
out[x] = VP8LSubPixels(in[x], pred); \
|
out[x] = VP8LSubPixels(in[x], pred); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
GENERATE_PREDICTOR_SUB(2)
|
GENERATE_PREDICTOR_SUB(2)
|
||||||
GENERATE_PREDICTOR_SUB(3)
|
GENERATE_PREDICTOR_SUB(3)
|
||||||
|
|||||||
@@ -14,10 +14,9 @@
|
|||||||
#include "src/dsp/dsp.h"
|
#include "src/dsp/dsp.h"
|
||||||
|
|
||||||
#if defined(WEBP_USE_AVX2)
|
#if defined(WEBP_USE_AVX2)
|
||||||
|
#include <assert.h>
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "src/dsp/cpu.h"
|
#include "src/dsp/cpu.h"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user