mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 18:35:41 +01:00 
			
		
		
		
	convert to ANSI-C
This commit is contained in:
		
				
					committed by
					
						 Pascal Massimino
						Pascal Massimino
					
				
			
			
				
	
			
			
			
						parent
						
							c3f41cb47e
						
					
				
				
					commit
					c8d15efa12
				
			
							
								
								
									
										4
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -1,3 +1,5 @@ | ||||
| Main stuff: | ||||
| Initial release: | ||||
| - Pascal Massimino (pascal.massimino@gmail.com) | ||||
|  | ||||
| Contributors: | ||||
| - pierre.php@gmail.com   (ansi-C port) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ LOCAL_SRC_FILES := \ | ||||
|  | ||||
| LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD \ | ||||
|                 -finline-functions -frename-registers -ffast-math \ | ||||
|                 -s -fomit-frame-pointer -std=gnu99 | ||||
|                 -s -fomit-frame-pointer | ||||
|  | ||||
| LOCAL_C_INCLUDES += $(LOCAL_PATH)/src | ||||
|  | ||||
|   | ||||
							
								
								
									
										201
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										201
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -19742,207 +19742,6 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool' | ||||
|  | ||||
|  | ||||
|  | ||||
|    { echo "$as_me:$LINENO: checking for $CC option to accept ISO C99" >&5 | ||||
| echo $ECHO_N "checking for $CC option to accept ISO C99... $ECHO_C" >&6; } | ||||
| if test "${ac_cv_prog_cc_c99+set}" = set; then | ||||
|   echo $ECHO_N "(cached) $ECHO_C" >&6 | ||||
| else | ||||
|   ac_cv_prog_cc_c99=no | ||||
| ac_save_CC=$CC | ||||
| cat >conftest.$ac_ext <<_ACEOF | ||||
| /* confdefs.h.  */ | ||||
| _ACEOF | ||||
| cat confdefs.h >>conftest.$ac_ext | ||||
| cat >>conftest.$ac_ext <<_ACEOF | ||||
| /* end confdefs.h.  */ | ||||
| #include <stdarg.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.h> | ||||
| #include <wchar.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| // Check varargs macros.  These examples are taken from C99 6.10.3.5. | ||||
| #define debug(...) fprintf (stderr, __VA_ARGS__) | ||||
| #define showlist(...) puts (#__VA_ARGS__) | ||||
| #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) | ||||
| static void | ||||
| test_varargs_macros (void) | ||||
| { | ||||
|   int x = 1234; | ||||
|   int y = 5678; | ||||
|   debug ("Flag"); | ||||
|   debug ("X = %d\n", x); | ||||
|   showlist (The first, second, and third items.); | ||||
|   report (x>y, "x is %d but y is %d", x, y); | ||||
| } | ||||
|  | ||||
| // Check long long types. | ||||
| #define BIG64 18446744073709551615ull | ||||
| #define BIG32 4294967295ul | ||||
| #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) | ||||
| #if !BIG_OK | ||||
|   your preprocessor is broken; | ||||
| #endif | ||||
| #if BIG_OK | ||||
| #else | ||||
|   your preprocessor is broken; | ||||
| #endif | ||||
| static long long int bignum = -9223372036854775807LL; | ||||
| static unsigned long long int ubignum = BIG64; | ||||
|  | ||||
| struct incomplete_array | ||||
| { | ||||
|   int datasize; | ||||
|   double data[]; | ||||
| }; | ||||
|  | ||||
| struct named_init { | ||||
|   int number; | ||||
|   const wchar_t *name; | ||||
|   double average; | ||||
| }; | ||||
|  | ||||
| typedef const char *ccp; | ||||
|  | ||||
| static inline int | ||||
| test_restrict (ccp restrict text) | ||||
| { | ||||
|   // See if C++-style comments work. | ||||
|   // Iterate through items via the restricted pointer. | ||||
|   // Also check for declarations in for loops. | ||||
|   for (unsigned int i = 0; *(text+i) != '\0'; ++i) | ||||
|     continue; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| // Check varargs and va_copy. | ||||
| static void | ||||
| test_varargs (const char *format, ...) | ||||
| { | ||||
|   va_list args; | ||||
|   va_start (args, format); | ||||
|   va_list args_copy; | ||||
|   va_copy (args_copy, args); | ||||
|  | ||||
|   const char *str; | ||||
|   int number; | ||||
|   float fnumber; | ||||
|  | ||||
|   while (*format) | ||||
|     { | ||||
|       switch (*format++) | ||||
| 	{ | ||||
| 	case 's': // string | ||||
| 	  str = va_arg (args_copy, const char *); | ||||
| 	  break; | ||||
| 	case 'd': // int | ||||
| 	  number = va_arg (args_copy, int); | ||||
| 	  break; | ||||
| 	case 'f': // float | ||||
| 	  fnumber = va_arg (args_copy, double); | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  break; | ||||
| 	} | ||||
|     } | ||||
|   va_end (args_copy); | ||||
|   va_end (args); | ||||
| } | ||||
|  | ||||
| int | ||||
| main () | ||||
| { | ||||
|  | ||||
|   // Check bool. | ||||
|   _Bool success = false; | ||||
|  | ||||
|   // Check restrict. | ||||
|   if (test_restrict ("String literal") == 0) | ||||
|     success = true; | ||||
|   char *restrict newvar = "Another string"; | ||||
|  | ||||
|   // Check varargs. | ||||
|   test_varargs ("s, d' f .", "string", 65, 34.234); | ||||
|   test_varargs_macros (); | ||||
|  | ||||
|   // Check flexible array members. | ||||
|   struct incomplete_array *ia = | ||||
|     malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); | ||||
|   ia->datasize = 10; | ||||
|   for (int i = 0; i < ia->datasize; ++i) | ||||
|     ia->data[i] = i * 1.234; | ||||
|  | ||||
|   // Check named initializers. | ||||
|   struct named_init ni = { | ||||
|     .number = 34, | ||||
|     .name = L"Test wide string", | ||||
|     .average = 543.34343, | ||||
|   }; | ||||
|  | ||||
|   ni.number = 58; | ||||
|  | ||||
|   int dynamic_array[ni.number]; | ||||
|   dynamic_array[ni.number - 1] = 543; | ||||
|  | ||||
|   // work around unused variable warnings | ||||
|   return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' | ||||
| 	  || dynamic_array[ni.number - 1] != 543); | ||||
|  | ||||
|   ; | ||||
|   return 0; | ||||
| } | ||||
| _ACEOF | ||||
| for ac_arg in '' -std=gnu99 -c99 -qlanglvl=extc99 | ||||
| do | ||||
|   CC="$ac_save_CC $ac_arg" | ||||
|   rm -f conftest.$ac_objext | ||||
| if { (ac_try="$ac_compile" | ||||
| case "(($ac_try" in | ||||
|   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; | ||||
|   *) ac_try_echo=$ac_try;; | ||||
| esac | ||||
| eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 | ||||
|   (eval "$ac_compile") 2>conftest.er1 | ||||
|   ac_status=$? | ||||
|   grep -v '^ *+' conftest.er1 >conftest.err | ||||
|   rm -f conftest.er1 | ||||
|   cat conftest.err >&5 | ||||
|   echo "$as_me:$LINENO: \$? = $ac_status" >&5 | ||||
|   (exit $ac_status); } && { | ||||
| 	 test -z "$ac_c_werror_flag" || | ||||
| 	 test ! -s conftest.err | ||||
|        } && test -s conftest.$ac_objext; then | ||||
|   ac_cv_prog_cc_c99=$ac_arg | ||||
| else | ||||
|   echo "$as_me: failed program was:" >&5 | ||||
| sed 's/^/| /' conftest.$ac_ext >&5 | ||||
|  | ||||
|  | ||||
| fi | ||||
|  | ||||
| rm -f core conftest.err conftest.$ac_objext | ||||
|   test "x$ac_cv_prog_cc_c99" != "xno" && break | ||||
| done | ||||
| rm -f conftest.$ac_ext | ||||
| CC=$ac_save_CC | ||||
|  | ||||
| fi | ||||
| # AC_CACHE_VAL | ||||
| case "x$ac_cv_prog_cc_c99" in | ||||
|   x) | ||||
|     { echo "$as_me:$LINENO: result: none needed" >&5 | ||||
| echo "${ECHO_T}none needed" >&6; } ;; | ||||
|   xno) | ||||
|     { echo "$as_me:$LINENO: result: unsupported" >&5 | ||||
| echo "${ECHO_T}unsupported" >&6; } ;; | ||||
|   *) | ||||
|     CC="$CC $ac_cv_prog_cc_c99" | ||||
|     { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c99" >&5 | ||||
| echo "${ECHO_T}$ac_cv_prog_cc_c99" >&6; } ;; | ||||
| esac | ||||
|  | ||||
|  | ||||
|  | ||||
| ac_config_headers="$ac_config_headers config.h" | ||||
|  | ||||
| ac_config_files="$ac_config_files Makefile examples/Makefile src/Makefile" | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| AC_INIT([webpdecode], [0.1]) | ||||
| AM_INIT_AUTOMAKE | ||||
| AC_PROG_LIBTOOL | ||||
| AC_PROG_CC_C99 | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| AC_CONFIG_FILES([Makefile examples/Makefile src/Makefile]) | ||||
| AC_OUTPUT | ||||
|   | ||||
							
								
								
									
										93
									
								
								src/dsp.c
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								src/dsp.c
									
									
									
									
									
								
							| @@ -32,17 +32,18 @@ static int tables_ok = 0; | ||||
|  | ||||
| void VP8DspInitTables() { | ||||
|   if (!tables_ok) { | ||||
|     for (int i = -255; i <= 255; ++i) { | ||||
|     int i; | ||||
|     for (i = -255; i <= 255; ++i) { | ||||
|       abs0[255 + i] = (i < 0) ? -i : i; | ||||
|       abs1[255 + i] = abs0[255 + i] >> 1; | ||||
|     } | ||||
|     for (int i = -1020; i <= 1020; ++i) { | ||||
|     for (i = -1020; i <= 1020; ++i) { | ||||
|       sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i; | ||||
|     } | ||||
|     for (int i = -112; i <= 112; ++i) { | ||||
|     for (i = -112; i <= 112; ++i) { | ||||
|       sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i; | ||||
|     } | ||||
|     for (int i = -255; i <= 255 + 255; ++i) { | ||||
|     for (i = -255; i <= 255 + 255; ++i) { | ||||
|       clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i; | ||||
|     } | ||||
|     tables_ok = 1; | ||||
| @@ -66,8 +67,9 @@ static const int kC2 = 35468; | ||||
|  | ||||
| static void Transform(const int16_t* in, uint8_t* dst) { | ||||
|   int C[4 * 4], *tmp; | ||||
|   int i; | ||||
|   tmp = C; | ||||
|   for (int i = 0; i < 4; ++i) {    // vertical pass | ||||
|   for (i = 0; i < 4; ++i) {    // vertical pass | ||||
|     const int a = in[0] + in[8]; | ||||
|     const int b = in[0] - in[8]; | ||||
|     const int c = MUL(in[4], kC2) - MUL(in[12], kC1); | ||||
| @@ -81,7 +83,7 @@ static void Transform(const int16_t* in, uint8_t* dst) { | ||||
|   } | ||||
|  | ||||
|   tmp = C; | ||||
|   for (int i = 0; i < 4; ++i) {    // horizontal pass | ||||
|   for (i = 0; i < 4; ++i) {    // horizontal pass | ||||
|     const int dc = tmp[0] + 4; | ||||
|     const int a =  dc +  tmp[8]; | ||||
|     const int b =  dc -  tmp[8]; | ||||
| @@ -106,8 +108,9 @@ static void TransformUV(const int16_t* in, uint8_t* dst) { | ||||
|  | ||||
| static void TransformDC(const int16_t *in, uint8_t* dst) { | ||||
|   const int DC = in[0] + 4; | ||||
|   for (int j = 0; j < 4; ++j) { | ||||
|     for (int i = 0; i < 4; ++i) { | ||||
|   int i, j; | ||||
|   for (j = 0; j < 4; ++j) { | ||||
|     for (i = 0; i < 4; ++i) { | ||||
|       STORE(i, j, DC); | ||||
|     } | ||||
|   } | ||||
| @@ -133,7 +136,8 @@ VP8Idct VP8TransformDCUV = TransformDCUV; | ||||
|  | ||||
| static void TransformWHT(const int16_t* in, int16_t* out) { | ||||
|   int tmp[16]; | ||||
|   for (int i = 0; i < 4; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 4; ++i) { | ||||
|     const int a0 = in[0 + i] + in[12 + i]; | ||||
|     const int a1 = in[4 + i] + in[ 8 + i]; | ||||
|     const int a2 = in[4 + i] - in[ 8 + i]; | ||||
| @@ -143,7 +147,7 @@ static void TransformWHT(const int16_t* in, int16_t* out) { | ||||
|     tmp[4  + i] = a3 + a2; | ||||
|     tmp[12 + i] = a3 - a2; | ||||
|   } | ||||
|   for (int i = 0; i < 4; ++i) { | ||||
|   for (i = 0; i < 4; ++i) { | ||||
|     const int dc = tmp[0 + i * 4] + 3;    // w/ rounder | ||||
|     const int a0 = dc             + tmp[3 + i * 4]; | ||||
|     const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4]; | ||||
| @@ -167,9 +171,11 @@ void (*VP8TransformWHT)(const int16_t* in, int16_t* out) = TransformWHT; | ||||
| static inline void TrueMotion(uint8_t *dst, int size) { | ||||
|   const uint8_t* top = dst - BPS; | ||||
|   const int tl = top[-1]; | ||||
|   for (int y = 0; y < size; ++y) { | ||||
|   int x, y; | ||||
|  | ||||
|   for (y = 0; y < size; ++y) { | ||||
|     const uint8_t* const clip = clip1 + 255 + dst[-1] - tl; | ||||
|     for (int x = 0; x < size; ++x) { | ||||
|     for (x = 0; x < size; ++x) { | ||||
|       dst[x] = clip[top[x]]; | ||||
|     } | ||||
|     dst += BPS; | ||||
| @@ -183,27 +189,31 @@ static void TM16(uint8_t *dst) { TrueMotion(dst, 16); } | ||||
| // 16x16 | ||||
|  | ||||
| static void V16(uint8_t *dst) {     // vertical | ||||
|   for (int j = 0; j < 16; ++j) { | ||||
|   int j; | ||||
|   for (j = 0; j < 16; ++j) { | ||||
|     memcpy(dst + j * BPS, dst - BPS, 16); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void H16(uint8_t *dst) {     // horizontal | ||||
|   for (int j = 16; j > 0; --j) { | ||||
|   int j; | ||||
|   for (j = 16; j > 0; --j) { | ||||
|     memset(dst, dst[-1], 16); | ||||
|     dst += BPS; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static inline void Put16(int v, uint8_t* dst) { | ||||
|   for (int j = 0; j < 16; ++j) { | ||||
|   int j; | ||||
|   for (j = 0; j < 16; ++j) { | ||||
|     memset(dst + j * BPS, v, 16); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void DC16(uint8_t *dst) {    // DC | ||||
|   int DC = 16; | ||||
|   for (int j = 0; j < 16; ++j) { | ||||
|   int j; | ||||
|   for (j = 0; j < 16; ++j) { | ||||
|     DC += dst[-1 + j * BPS] + dst[j - BPS]; | ||||
|   } | ||||
|   Put16(DC >> 5, dst); | ||||
| @@ -235,7 +245,8 @@ static void DC16NoTopLeft(uint8_t *dst) {  // DC with no top and left samples | ||||
| // 4x4 | ||||
|  | ||||
| static inline void Put4(uint32_t v, uint8_t* dst) { | ||||
|   for (int i = 4; i > 0; --i) { | ||||
|   int i; | ||||
|   for (i = 4; i > 0; --i) { | ||||
|     *(uint32_t*)dst = v; | ||||
|     dst += BPS; | ||||
|   } | ||||
| @@ -270,7 +281,8 @@ static void H4(uint8_t *dst) {    // horizontal | ||||
|  | ||||
| static void DC4(uint8_t *dst) {   // DC | ||||
|   uint32_t dc = 4; | ||||
|   for (int i = 0; i < 4; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 4; ++i) { | ||||
|     dc += dst[i - BPS] + dst[-1 + i * BPS]; | ||||
|   } | ||||
|   Put4((dc >> 3) * 0x01010101U, dst); | ||||
| @@ -402,13 +414,15 @@ static void HD4(uint8_t *dst) {  // Horizontal-Down | ||||
| // Chroma | ||||
|  | ||||
| static void V8uv(uint8_t *dst) {    // vertical | ||||
|   for (int j = 0; j < 8; ++j) { | ||||
|   int j; | ||||
|   for (j = 0; j < 8; ++j) { | ||||
|     memcpy(dst + j * BPS, dst - BPS, 8); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void H8uv(uint8_t *dst) {    // horizontal | ||||
|   for (int j = 0; j < 8; ++j) { | ||||
|   int j; | ||||
|   for (j = 0; j < 8; ++j) { | ||||
|     memset(dst, dst[-1], 8); | ||||
|     dst += BPS; | ||||
|   } | ||||
| @@ -416,36 +430,37 @@ static void H8uv(uint8_t *dst) {    // horizontal | ||||
|  | ||||
| // helper for chroma-DC predictions | ||||
| static inline void Put8x8uv(uint64_t v, uint8_t* dst) { | ||||
|   for (int j = 0; j < 8; ++j) { | ||||
|   int j; | ||||
|   for (j = 0; j < 8; ++j) { | ||||
|     *(uint64_t*)(dst + j * BPS) = v; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void DC8uv(uint8_t *dst) {     // DC | ||||
|   int dc0 = 8; | ||||
|   for (int i = 0; i < 8; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 8; ++i) { | ||||
|     dc0 += dst[i - BPS] + dst[-1 + i * BPS]; | ||||
|   } | ||||
|   const uint64_t t = (dc0 >> 4) * 0x0101010101010101ULL; | ||||
|   Put8x8uv(t, dst); | ||||
|   Put8x8uv((uint64_t)((dc0 >> 4) * 0x0101010101010101ULL), dst); | ||||
| } | ||||
|  | ||||
| static void DC8uvNoLeft(uint8_t *dst) {   // DC with no left samples | ||||
|   int dc0 = 4; | ||||
|   for (int i = 0; i < 8; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 8; ++i) { | ||||
|     dc0 += dst[i - BPS]; | ||||
|   } | ||||
|   const uint64_t v = (dc0 >> 3) * 0x0101010101010101ULL; | ||||
|   Put8x8uv(v, dst); | ||||
|   Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst); | ||||
| } | ||||
|  | ||||
| static void DC8uvNoTop(uint8_t *dst) {  // DC with no top samples | ||||
|   int dc0 = 4; | ||||
|   for (int i = 0; i < 8; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 8; ++i) { | ||||
|     dc0 += dst[-1 + i * BPS]; | ||||
|   } | ||||
|   const uint64_t v = (dc0 >> 3) * 0x0101010101010101ULL; | ||||
|   Put8x8uv(v, dst); | ||||
|   Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst); | ||||
| } | ||||
|  | ||||
| static void DC8uvNoTopLeft(uint8_t *dst) {    // DC with nothing | ||||
| @@ -535,7 +550,8 @@ static inline int needs_filter2(const uint8_t* p, int step, int t, int it) { | ||||
| // Simple In-loop filtering (Paragraph 15.2) | ||||
|  | ||||
| static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { | ||||
|   for (int i = 0; i < 16; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 16; ++i) { | ||||
|     if (needs_filter(p + i, stride, thresh)) { | ||||
|       do_filter2(p + i, stride); | ||||
|     } | ||||
| @@ -543,7 +559,8 @@ static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { | ||||
| } | ||||
|  | ||||
| static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { | ||||
|   for (int i = 0; i < 16; ++i) { | ||||
|   int i; | ||||
|   for (i = 0; i < 16; ++i) { | ||||
|     if (needs_filter(p + i * stride, 1, thresh)) { | ||||
|       do_filter2(p + i * stride, 1); | ||||
|     } | ||||
| @@ -551,14 +568,16 @@ static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { | ||||
| } | ||||
|  | ||||
| static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { | ||||
|   for (int k = 3; k > 0; --k) { | ||||
|   int k; | ||||
|   for (k = 3; k > 0; --k) { | ||||
|     p += 4 * stride; | ||||
|     SimpleVFilter16(p, stride, thresh); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { | ||||
|   for (int k = 3; k > 0; --k) { | ||||
|   int k; | ||||
|   for (k = 3; k > 0; --k) { | ||||
|     p += 4; | ||||
|     SimpleHFilter16(p, stride, thresh); | ||||
|   } | ||||
| @@ -609,7 +628,8 @@ static void HFilter16(uint8_t* p, int stride, | ||||
| // on three inner edges | ||||
| static void VFilter16i(uint8_t* p, int stride, | ||||
|                        int thresh, int ithresh, int hev_thresh) { | ||||
|   for (int k = 3; k > 0; --k) { | ||||
|   int k; | ||||
|   for (k = 3; k > 0; --k) { | ||||
|     p += 4 * stride; | ||||
|     FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); | ||||
|   } | ||||
| @@ -617,7 +637,8 @@ static void VFilter16i(uint8_t* p, int stride, | ||||
|  | ||||
| static void HFilter16i(uint8_t* p, int stride, | ||||
|                        int thresh, int ithresh, int hev_thresh) { | ||||
|   for (int k = 3; k > 0; --k) { | ||||
|   int k; | ||||
|   for (k = 3; k > 0; --k) { | ||||
|     p += 4; | ||||
|     FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); | ||||
|   } | ||||
|   | ||||
							
								
								
									
										254
									
								
								src/frame.c
									
									
									
									
									
								
							
							
						
						
									
										254
									
								
								src/frame.c
									
									
									
									
									
								
							| @@ -38,6 +38,8 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* io) { | ||||
|                    + top_size + info_size | ||||
|                    + yuv_size + coeffs_size | ||||
|                    + cache_size + ALIGN_MASK; | ||||
|   uint8_t* mem; | ||||
|  | ||||
|   if (needed > dec->mem_size_) { | ||||
|     free(dec->mem_); | ||||
|     dec->mem_size_ = 0; | ||||
| @@ -48,7 +50,7 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* io) { | ||||
|     dec->mem_size_ = needed; | ||||
|   } | ||||
|  | ||||
|   uint8_t* mem = (uint8_t*)dec->mem_; | ||||
|   mem = (uint8_t*)dec->mem_; | ||||
|   dec->intra_t_ = (uint8_t*)mem; | ||||
|   mem += intra_pred_mode_size; | ||||
|  | ||||
| @@ -198,65 +200,71 @@ void VP8StoreBlock(VP8Decoder* const dec) { | ||||
|       level = 9 - dec->filter_hdr_.sharpness_; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   info->f_ilevel_ = (level < 1) ? 1 : level; | ||||
|   info->f_inner_ = (!info->skip_ || dec->is_i4x4_); | ||||
|  | ||||
|   // Transfer samples to row cache | ||||
|   uint8_t* const ydst = dec->cache_y_ + dec->mb_x_ * 16; | ||||
|   uint8_t* const udst = dec->cache_u_ + dec->mb_x_ * 8; | ||||
|   uint8_t* const vdst = dec->cache_v_ + dec->mb_x_ * 8; | ||||
|   for (int y = 0; y < 16; ++y) { | ||||
|     memcpy(ydst + y * dec->cache_y_stride_, | ||||
|            dec->yuv_b_ + Y_OFF + y * BPS, 16); | ||||
|   } | ||||
|   for (int y = 0; y < 8; ++y) { | ||||
|     memcpy(udst + y * dec->cache_uv_stride_, | ||||
|   { | ||||
|     // Transfer samples to row cache | ||||
|     int y; | ||||
|     uint8_t* const ydst = dec->cache_y_ + dec->mb_x_ * 16; | ||||
|     uint8_t* const udst = dec->cache_u_ + dec->mb_x_ * 8; | ||||
|     uint8_t* const vdst = dec->cache_v_ + dec->mb_x_ * 8; | ||||
|     for (y = 0; y < 16; ++y) { | ||||
|       memcpy(ydst + y * dec->cache_y_stride_, | ||||
|              dec->yuv_b_ + Y_OFF + y * BPS, 16); | ||||
|     } | ||||
|     for (y = 0; y < 8; ++y) { | ||||
|       memcpy(udst + y * dec->cache_uv_stride_, | ||||
|            dec->yuv_b_ + U_OFF + y * BPS, 8); | ||||
|     memcpy(vdst + y * dec->cache_uv_stride_, | ||||
|       memcpy(vdst + y * dec->cache_uv_stride_, | ||||
|            dec->yuv_b_ + V_OFF + y * BPS, 8); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void VP8FilterRow(VP8Decoder* const dec, VP8Io* io) { | ||||
|   for (int mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { | ||||
|   int mb_x; | ||||
|   for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { | ||||
|     DoFilter(dec, mb_x, dec->mb_y_); | ||||
|   } | ||||
|   const int extra_y_rows = kFilterExtraRows[dec->filter_type_]; | ||||
|   const int ysize = extra_y_rows * dec->cache_y_stride_; | ||||
|   const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_; | ||||
|   uint8_t* const ydst = dec->cache_y_ - ysize; | ||||
|   uint8_t* const udst = dec->cache_u_ - uvsize; | ||||
|   uint8_t* const vdst = dec->cache_v_ - uvsize; | ||||
|   if (io->put) { | ||||
|     int y_end; | ||||
|     if (dec->mb_y_ > 0) { | ||||
|       io->mb_y = dec->mb_y_ * 16 - extra_y_rows; | ||||
|       io->y = ydst; | ||||
|       io->u = udst; | ||||
|       io->v = vdst; | ||||
|       if (dec->mb_y_ < dec->mb_h_ - 1) { | ||||
|         y_end = io->mb_y + 16; | ||||
|       } else { | ||||
|         y_end = io->height;   // last macroblock row. | ||||
|   { | ||||
|     const int extra_y_rows = kFilterExtraRows[dec->filter_type_]; | ||||
|     const int ysize = extra_y_rows * dec->cache_y_stride_; | ||||
|     const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_; | ||||
|     uint8_t* const ydst = dec->cache_y_ - ysize; | ||||
|     uint8_t* const udst = dec->cache_u_ - uvsize; | ||||
|     uint8_t* const vdst = dec->cache_v_ - uvsize; | ||||
|     if (io->put) { | ||||
|       int y_end; | ||||
|       if (dec->mb_y_ > 0) { | ||||
|         io->mb_y = dec->mb_y_ * 16 - extra_y_rows; | ||||
|         io->y = ydst; | ||||
|         io->u = udst; | ||||
|         io->v = vdst; | ||||
|         if (dec->mb_y_ < dec->mb_h_ - 1) { | ||||
|           y_end = io->mb_y + 16; | ||||
|         } else { | ||||
|           y_end = io->height;   // last macroblock row. | ||||
|         } | ||||
|       } else {   // first macroblock row. | ||||
|         io->mb_y = 0; | ||||
|         y_end = 16 - extra_y_rows; | ||||
|         io->y = dec->cache_y_; | ||||
|         io->u = dec->cache_u_; | ||||
|         io->v = dec->cache_v_; | ||||
|       } | ||||
|     } else {   // first macroblock row. | ||||
|       io->mb_y = 0; | ||||
|       y_end = 16 - extra_y_rows; | ||||
|       io->y = dec->cache_y_; | ||||
|       io->u = dec->cache_u_; | ||||
|       io->v = dec->cache_v_; | ||||
|       if (y_end > io->height) { | ||||
|         y_end = io->height; | ||||
|       } | ||||
|       io->mb_h = y_end - io->mb_y; | ||||
|       io->put(io); | ||||
|     } | ||||
|     if (y_end > io->height) { | ||||
|       y_end = io->height; | ||||
|     // rotate top samples | ||||
|     if (dec->mb_y_ < dec->mb_h_ - 1) { | ||||
|       memcpy(ydst, ydst + 16 * dec->cache_y_stride_, ysize); | ||||
|       memcpy(udst, udst + 8 * dec->cache_uv_stride_, uvsize); | ||||
|       memcpy(vdst, vdst + 8 * dec->cache_uv_stride_, uvsize); | ||||
|     } | ||||
|     io->mb_h = y_end - io->mb_y; | ||||
|     io->put(io); | ||||
|   } | ||||
|   // rotate top samples | ||||
|   if (dec->mb_y_ < dec->mb_h_ - 1) { | ||||
|     memcpy(ydst, ydst + 16 * dec->cache_y_stride_, ysize); | ||||
|     memcpy(udst, udst + 8 * dec->cache_uv_stride_, uvsize); | ||||
|     memcpy(vdst, vdst + 8 * dec->cache_uv_stride_, uvsize); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -294,18 +302,20 @@ void VP8ReconstructBlock(VP8Decoder* const dec) { | ||||
|   // Rotate in the left samples from previously decoded block. We move four | ||||
|   // pixels at a time for alignment reason, and because of in-loop filter. | ||||
|   if (dec->mb_x_ > 0) { | ||||
|     for (int j = -1; j < 16; ++j) { | ||||
|     int j; | ||||
|     for (j = -1; j < 16; ++j) { | ||||
|       Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]); | ||||
|     } | ||||
|     for (int j = -1; j < 8; ++j) { | ||||
|     for (j = -1; j < 8; ++j) { | ||||
|       Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]); | ||||
|       Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]); | ||||
|     } | ||||
|   } else { | ||||
|     for (int j = 0; j < 16; ++j) { | ||||
|     int j; | ||||
|     for (j = 0; j < 16; ++j) { | ||||
|       y_dst[j * BPS - 1] = 129; | ||||
|     } | ||||
|     for (int j = 0; j < 8; ++j) { | ||||
|     for (j = 0; j < 8; ++j) { | ||||
|       u_dst[j * BPS - 1] = 129; | ||||
|       v_dst[j * BPS - 1] = 129; | ||||
|     } | ||||
| @@ -314,90 +324,96 @@ void VP8ReconstructBlock(VP8Decoder* const dec) { | ||||
|       y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129; | ||||
|     } | ||||
|   } | ||||
|   { | ||||
|     // bring top samples into the cache | ||||
|     uint8_t* const top_y = dec->y_t_ + dec->mb_x_ * 16; | ||||
|     uint8_t* const top_u = dec->u_t_ + dec->mb_x_ * 8; | ||||
|     uint8_t* const top_v = dec->v_t_ + dec->mb_x_ * 8; | ||||
|     const int16_t* coeffs = dec->coeffs_; | ||||
|     int n; | ||||
|  | ||||
|   // bring top samples into the cache | ||||
|   uint8_t* const top_y = dec->y_t_ + dec->mb_x_ * 16; | ||||
|   uint8_t* const top_u = dec->u_t_ + dec->mb_x_ * 8; | ||||
|   uint8_t* const top_v = dec->v_t_ + dec->mb_x_ * 8; | ||||
|   if (dec->mb_y_ > 0) { | ||||
|     memcpy(y_dst - BPS, top_y, 16); | ||||
|     memcpy(u_dst - BPS, top_u, 8); | ||||
|     memcpy(v_dst - BPS, top_v, 8); | ||||
|   } else if (dec->mb_x_ == 0) { | ||||
|     // we only need to do this init once at block (0,0). | ||||
|     // Afterward, it remains valid for the whole topmost row. | ||||
|     memset(y_dst - BPS - 1, 127, 16 + 4 + 1); | ||||
|     memset(u_dst - BPS - 1, 127, 8 + 1); | ||||
|     memset(v_dst - BPS - 1, 127, 8 + 1); | ||||
|   } | ||||
|  | ||||
|   // predict and add residuals | ||||
|   const int16_t* coeffs = dec->coeffs_; | ||||
|   if (dec->is_i4x4_) {   // 4x4 | ||||
|     uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16); | ||||
|     if (dec->mb_y_ > 0) { | ||||
|       if (dec->mb_x_ >= dec->mb_w_ - 1) {    // on rightmost border | ||||
|         top_right[0] = top_y[15] * 0x01010101u; | ||||
|       } else { | ||||
|         memcpy(top_right, top_y + 16, sizeof(*top_right)); | ||||
|       } | ||||
|       memcpy(y_dst - BPS, top_y, 16); | ||||
|       memcpy(u_dst - BPS, top_u, 8); | ||||
|       memcpy(v_dst - BPS, top_v, 8); | ||||
|     } else if (dec->mb_x_ == 0) { | ||||
|       // we only need to do this init once at block (0,0). | ||||
|       // Afterward, it remains valid for the whole topmost row. | ||||
|       memset(y_dst - BPS - 1, 127, 16 + 4 + 1); | ||||
|       memset(u_dst - BPS - 1, 127, 8 + 1); | ||||
|       memset(v_dst - BPS - 1, 127, 8 + 1); | ||||
|     } | ||||
|     // replicate the top-right pixels below | ||||
|     top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0]; | ||||
|  | ||||
|     // predict and add residues for all 4x4 blocks in turn. | ||||
|     for (int n = 0; n < 16; n++) { | ||||
|       uint8_t* const dst = y_dst + kScan[n]; | ||||
|       VP8PredLuma4[dec->imodes_[n]](dst); | ||||
|       if (dec->non_zero_ & (1 << n)) { | ||||
|         VP8Transform(coeffs + n * 16, dst); | ||||
|       } else if (dec->non_zero_ & (1 << n)) {  // only DC is present | ||||
|         VP8TransformDC(coeffs + n * 16, dst); | ||||
|     // predict and add residuals | ||||
|  | ||||
|     if (dec->is_i4x4_) {   // 4x4 | ||||
|       uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16); | ||||
|  | ||||
|       if (dec->mb_y_ > 0) { | ||||
|         if (dec->mb_x_ >= dec->mb_w_ - 1) {    // on rightmost border | ||||
|           top_right[0] = top_y[15] * 0x01010101u; | ||||
|         } else { | ||||
|           memcpy(top_right, top_y + 16, sizeof(*top_right)); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } else {    // 16x16 | ||||
|     const int pred_func = CheckMode(dec, dec->imodes_[0]); | ||||
|     VP8PredLuma16[pred_func](y_dst); | ||||
|     if (dec->non_zero_) { | ||||
|       for (int n = 0; n < 16; n++) { | ||||
|       // replicate the top-right pixels below | ||||
|       top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0]; | ||||
|  | ||||
|       // predict and add residues for all 4x4 blocks in turn. | ||||
|       for (n = 0; n < 16; n++) { | ||||
|         uint8_t* const dst = y_dst + kScan[n]; | ||||
|         if (dec->non_zero_ac_ & (1 << n)) { | ||||
|         VP8PredLuma4[dec->imodes_[n]](dst); | ||||
|         if (dec->non_zero_ & (1 << n)) { | ||||
|           VP8Transform(coeffs + n * 16, dst); | ||||
|         } else if (dec->non_zero_ & (1 << n)) {  // only DC is present | ||||
|           VP8TransformDC(coeffs + n * 16, dst); | ||||
|         } | ||||
|       } | ||||
|     } else {    // 16x16 | ||||
|       const int pred_func = CheckMode(dec, dec->imodes_[0]); | ||||
|       VP8PredLuma16[pred_func](y_dst); | ||||
|       if (dec->non_zero_) { | ||||
|         for (n = 0; n < 16; n++) { | ||||
|           uint8_t* const dst = y_dst + kScan[n]; | ||||
|           if (dec->non_zero_ac_ & (1 << n)) { | ||||
|             VP8Transform(coeffs + n * 16, dst); | ||||
|           } else if (dec->non_zero_ & (1 << n)) {  // only DC is present | ||||
|             VP8TransformDC(coeffs + n * 16, dst); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|     { | ||||
|       // Chroma | ||||
|       const int pred_func = CheckMode(dec, dec->uvmode_); | ||||
|       VP8PredChroma8[pred_func](u_dst); | ||||
|       VP8PredChroma8[pred_func](v_dst); | ||||
|  | ||||
|   // Chroma | ||||
|   const int pred_func = CheckMode(dec, dec->uvmode_); | ||||
|   VP8PredChroma8[pred_func](u_dst); | ||||
|   VP8PredChroma8[pred_func](v_dst); | ||||
|       if (dec->non_zero_ & 0x0f0000) {   // chroma-U | ||||
|         const int16_t* const u_coeffs = dec->coeffs_ + 16 * 16; | ||||
|         if (dec->non_zero_ac_ & 0x0f0000) { | ||||
|           VP8TransformUV(u_coeffs, u_dst); | ||||
|         } else { | ||||
|           VP8TransformDCUV(u_coeffs, u_dst); | ||||
|         } | ||||
|       } | ||||
|       if (dec->non_zero_ & 0xf00000) {   // chroma-V | ||||
|         const int16_t* const v_coeffs = dec->coeffs_ + 20 * 16; | ||||
|         if (dec->non_zero_ac_ & 0xf00000) { | ||||
|           VP8TransformUV(v_coeffs, v_dst); | ||||
|         } else { | ||||
|           VP8TransformDCUV(v_coeffs, v_dst); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|   if (dec->non_zero_ & 0x0f0000) {   // chroma-U | ||||
|     const int16_t* const u_coeffs = dec->coeffs_ + 16 * 16; | ||||
|     if (dec->non_zero_ac_ & 0x0f0000) { | ||||
|       VP8TransformUV(u_coeffs, u_dst); | ||||
|     } else { | ||||
|       VP8TransformDCUV(u_coeffs, u_dst); | ||||
|       // stash away top samples for next block | ||||
|       if (dec->mb_y_ < dec->mb_h_ - 1) { | ||||
|         memcpy(top_y, y_dst + 15 * BPS, 16); | ||||
|         memcpy(top_u, u_dst +  7 * BPS,  8); | ||||
|         memcpy(top_v, v_dst +  7 * BPS,  8); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   if (dec->non_zero_ & 0xf00000) {   // chroma-V | ||||
|     const int16_t* const v_coeffs = dec->coeffs_ + 20 * 16; | ||||
|     if (dec->non_zero_ac_ & 0xf00000) { | ||||
|       VP8TransformUV(v_coeffs, v_dst); | ||||
|     } else { | ||||
|       VP8TransformDCUV(v_coeffs, v_dst); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // stash away top samples for next block | ||||
|   if (dec->mb_y_ < dec->mb_h_ - 1) { | ||||
|     memcpy(top_y, y_dst + 15 * BPS, 16); | ||||
|     memcpy(top_u, u_dst +  7 * BPS,  8); | ||||
|     memcpy(top_v, v_dst +  7 * BPS,  8); | ||||
|   } | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/quant.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/quant.c
									
									
									
									
									
								
							| @@ -71,7 +71,9 @@ void VP8ParseQuant(VP8Decoder* const dec) { | ||||
|   const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; | ||||
|  | ||||
|   const VP8SegmentHeader* const hdr = &dec->segment_hdr_; | ||||
|   for (int i = 0; i < NUM_MB_SEGMENTS; ++i) { | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < NUM_MB_SEGMENTS; ++i) { | ||||
|     int q; | ||||
|     if (hdr->use_segment_) { | ||||
|       q = hdr->quantizer_[i]; | ||||
| @@ -86,17 +88,19 @@ void VP8ParseQuant(VP8Decoder* const dec) { | ||||
|         q = base_q0; | ||||
|       } | ||||
|     } | ||||
|     VP8QuantMatrix* const m = &dec->dqm_[i]; | ||||
|     m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)]; | ||||
|     m->y1_mat_[1] = kAcTable[clip(q + 0,       127)]; | ||||
|     { | ||||
|       VP8QuantMatrix* const m = &dec->dqm_[i]; | ||||
|       m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)]; | ||||
|       m->y1_mat_[1] = kAcTable[clip(q + 0,       127)]; | ||||
|  | ||||
|     m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2; | ||||
|     // TODO(skal): make it another table? | ||||
|     m->y2_mat_[1] = kAcTable[clip(q + dqy2_ac, 127)] * 155 / 100; | ||||
|     if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8; | ||||
|       m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2; | ||||
|       // TODO(skal): make it another table? | ||||
|       m->y2_mat_[1] = kAcTable[clip(q + dqy2_ac, 127)] * 155 / 100; | ||||
|       if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8; | ||||
|  | ||||
|     m->uv_mat_[0] = kDcTable[clip(q + dquv_ac, 117)]; | ||||
|     m->uv_mat_[1] = kAcTable[clip(q + dquv_dc, 127)]; | ||||
|       m->uv_mat_[0] = kDcTable[clip(q + dquv_ac, 117)]; | ||||
|       m->uv_mat_[1] = kAcTable[clip(q + dquv_dc, 127)]; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										15
									
								
								src/tree.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/tree.c
									
									
									
									
									
								
							| @@ -343,9 +343,11 @@ void VP8ParseIntraMode(VP8BitReader* const br,  VP8Decoder* const dec) { | ||||
|     memset(left, ymode, 4 * sizeof(left[0])); | ||||
|   } else { | ||||
|     uint8_t* modes = dec->imodes_; | ||||
|     for (int y = 0; y < 4; ++y) { | ||||
|     int y; | ||||
|     for (y = 0; y < 4; ++y) { | ||||
|       int ymode = left[y]; | ||||
|       for (int x = 0; x < 4; ++x) { | ||||
|       int x; | ||||
|       for (x = 0; x < 4; ++x) { | ||||
|         const uint8_t* const prob = kBModesProba[top[x]][ymode]; | ||||
| #ifdef USE_GENERIC_TREE | ||||
|         // Generic tree-parsing | ||||
| @@ -531,10 +533,11 @@ static const uint8_t MVUpdateProba[2][NUM_MV_PROBAS] = { | ||||
| // Paragraph 9.9 | ||||
| void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { | ||||
|   VP8Proba* const proba = &dec->proba_; | ||||
|   for (int t = 0; t < NUM_TYPES; ++t) { | ||||
|     for (int b = 0; b < NUM_BANDS; ++b) { | ||||
|       for (int c = 0; c < NUM_CTX; ++c) { | ||||
|         for (int p = 0; p < NUM_PROBAS; ++p) { | ||||
|   int t, b, c, p; | ||||
|   for (t = 0; t < NUM_TYPES; ++t) { | ||||
|     for (b = 0; b < NUM_BANDS; ++b) { | ||||
|       for (c = 0; c < NUM_CTX; ++c) { | ||||
|         for (p = 0; p < NUM_PROBAS; ++p) { | ||||
|           if (VP8GetBit(br, CoeffsUpdateProba[t][b][c][p])) { | ||||
|             proba->coeffs_[t][b][c][p] = VP8GetValue(br, 8); | ||||
|           } | ||||
|   | ||||
							
								
								
									
										108
									
								
								src/vp8.c
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								src/vp8.c
									
									
									
									
									
								
							| @@ -80,18 +80,19 @@ static int ParseSegmentHeader(VP8BitReader* br, | ||||
|   hdr->use_segment_ = VP8Get(br); | ||||
|   if (hdr->use_segment_) { | ||||
|     hdr->update_map_ = VP8Get(br); | ||||
|     const int update_data = VP8Get(br); | ||||
|     if (update_data) { | ||||
|     if (VP8Get(br)) {   // update data | ||||
|       int s; | ||||
|       hdr->absolute_delta_ = VP8Get(br); | ||||
|       for (int s = 0; s < NUM_MB_SEGMENTS; ++s) { | ||||
|       for (s = 0; s < NUM_MB_SEGMENTS; ++s) { | ||||
|         hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0; | ||||
|       } | ||||
|       for (int s = 0; s < NUM_MB_SEGMENTS; ++s) { | ||||
|       for (s = 0; s < NUM_MB_SEGMENTS; ++s) { | ||||
|         hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0; | ||||
|       } | ||||
|     } | ||||
|     if (hdr->update_map_) { | ||||
|       for (int s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { | ||||
|       int s; | ||||
|       for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { | ||||
|         proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u; | ||||
|       } | ||||
|     } | ||||
| @@ -105,14 +106,19 @@ static int ParseSegmentHeader(VP8BitReader* br, | ||||
| static int ParsePartitions(VP8Decoder* const dec, | ||||
|                            const uint8_t* buf, uint32_t size) { | ||||
|   VP8BitReader* const br = &dec->br_; | ||||
|   dec->num_parts_ = 1 << VP8GetValue(br, 2); | ||||
|   const uint8_t* sz = buf; | ||||
|   const int last_part = dec->num_parts_ - 1; | ||||
|   uint32_t offset = last_part * 3; | ||||
|   int last_part; | ||||
|   uint32_t offset; | ||||
|   int p; | ||||
|  | ||||
|   dec->num_parts_ = 1 << VP8GetValue(br, 2); | ||||
|   last_part = dec->num_parts_ - 1; | ||||
|   offset = last_part * 3; | ||||
|  | ||||
|   if (size <= offset) { | ||||
|     return 0; | ||||
|   } | ||||
|   for (int p = 0; p < last_part; ++p) { | ||||
|   for (p = 0; p < last_part; ++p) { | ||||
|     const uint32_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16); | ||||
|     if (offset + psize > size) { | ||||
|       return 0; | ||||
| @@ -135,12 +141,13 @@ static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { | ||||
|   hdr->use_lf_delta_ = VP8Get(br); | ||||
|   if (hdr->use_lf_delta_) { | ||||
|     if (VP8Get(br)) {   // update lf-delta? | ||||
|       for (int i = 0; i < NUM_REF_LF_DELTAS; ++i) { | ||||
|       int i; | ||||
|       for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { | ||||
|         if (VP8Get(br)) { | ||||
|           hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6); | ||||
|         } | ||||
|       } | ||||
|       for (int i = 0; i < NUM_MODE_LF_DELTAS; ++i) { | ||||
|       for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { | ||||
|         if (VP8Get(br)) { | ||||
|           hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6); | ||||
|         } | ||||
| @@ -150,7 +157,8 @@ static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { | ||||
|   dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2; | ||||
|   if (dec->filter_type_ > 0) {    // precompute filter levels per segment | ||||
|     if (dec->segment_hdr_.use_segment_) { | ||||
|       for (int s = 0; s < NUM_MB_SEGMENTS; ++s) { | ||||
|       int s; | ||||
|       for (s = 0; s < NUM_MB_SEGMENTS; ++s) { | ||||
|         int strength = dec->segment_hdr_.filter_strength_[s]; | ||||
|         if (!dec->segment_hdr_.absolute_delta_) { | ||||
|           strength += hdr->level_; | ||||
| @@ -170,6 +178,12 @@ static inline uint32_t get_le32(const uint8_t* const data) { | ||||
|  | ||||
| // Topmost call | ||||
| int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|   uint8_t* buf; | ||||
|   uint32_t buf_size; | ||||
|   VP8FrameHeader* frm_hdr; | ||||
|   VP8PictureHeader* pic_hdr; | ||||
|   VP8BitReader* br; | ||||
|  | ||||
|   if (dec == NULL) { | ||||
|     return 0; | ||||
|   } | ||||
| @@ -177,25 +191,28 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|   if (io == NULL || io->data == NULL || io->data_size <= 4) { | ||||
|     return VP8SetError(dec, 2, "null VP8Io passed to VP8GetHeaders()"); | ||||
|   } | ||||
|   const uint8_t* buf = io->data; | ||||
|   uint32_t buf_size = io->data_size; | ||||
|  | ||||
|   buf = (uint8_t *)io->data; | ||||
|   buf_size = io->data_size; | ||||
|   if (buf_size < 4) { | ||||
|     return VP8SetError(dec, 2, "Not enough data to parse frame header"); | ||||
|   } | ||||
|  | ||||
|   // Skip over valid RIFF headers | ||||
|   if (!memcmp(buf, "RIFF", 4)) { | ||||
|     uint32_t riff_size; | ||||
|     uint32_t chunk_size; | ||||
|     if (buf_size < 20 + 4) { | ||||
|       return VP8SetError(dec, 2, "RIFF: Truncated header."); | ||||
|     } | ||||
|     if (memcmp(buf + 8, "WEBP", 4)) {   // wrong image file signature | ||||
|       return VP8SetError(dec, 2, "RIFF: WEBP signature not found."); | ||||
|     } | ||||
|     const uint32_t riff_size = get_le32(buf + 4); | ||||
|     riff_size = get_le32(buf + 4); | ||||
|     if (memcmp(buf + 12, "VP8 ", 4)) { | ||||
|       return VP8SetError(dec, 2, "RIFF: Invalid compression format."); | ||||
|     } | ||||
|     const uint32_t chunk_size = get_le32(buf + 16); | ||||
|     chunk_size = get_le32(buf + 16); | ||||
|     if ((chunk_size > riff_size + 8) || (chunk_size & 1)) { | ||||
|       return VP8SetError(dec, 2, "RIFF: Inconsistent size information."); | ||||
|     } | ||||
| @@ -204,16 +221,18 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|   } | ||||
|  | ||||
|   // Paragraph 9.1 | ||||
|   VP8FrameHeader* const frm_hdr = &dec->frm_hdr_; | ||||
|   const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); | ||||
|   frm_hdr->key_frame_ = !(bits & 1); | ||||
|   frm_hdr->profile_ = (bits >> 1) & 7; | ||||
|   frm_hdr->show_ = (bits >> 4) & 1; | ||||
|   frm_hdr->partition_length_ = (bits >> 5); | ||||
|   buf += 3; | ||||
|   buf_size -= 3; | ||||
|   { | ||||
|     frm_hdr = &dec->frm_hdr_; | ||||
|     const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); | ||||
|     frm_hdr->key_frame_ = !(bits & 1); | ||||
|     frm_hdr->profile_ = (bits >> 1) & 7; | ||||
|     frm_hdr->show_ = (bits >> 4) & 1; | ||||
|     frm_hdr->partition_length_ = (bits >> 5); | ||||
|     buf += 3; | ||||
|     buf_size -= 3; | ||||
|   } | ||||
|  | ||||
|   VP8PictureHeader* const pic_hdr = &dec->pic_hdr_; | ||||
|   pic_hdr = &dec->pic_hdr_; | ||||
|   if (frm_hdr->key_frame_) { | ||||
|     // Paragraph 9.2 | ||||
|     if (buf_size < 7) { | ||||
| @@ -239,7 +258,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|     dec->segment_ = 0;    // default for intra | ||||
|   } | ||||
|  | ||||
|   VP8BitReader* const br = &dec->br_; | ||||
|   br = &dec->br_; | ||||
|   VP8Init(br, buf, buf_size); | ||||
|   buf += frm_hdr->partition_length_; | ||||
|   buf_size -= frm_hdr->partition_length_; | ||||
| @@ -333,7 +352,7 @@ static int GetCoeffs(VP8BitReader* const br, | ||||
|     if (!VP8GetBit(br, p[1])) { | ||||
|       p = prob[kBands[n]][0]; | ||||
|     } else {  // non zero coeff | ||||
|       int v; | ||||
|       int v, j; | ||||
|       if (!VP8GetBit(br, p[2])) { | ||||
|         p = prob[kBands[n]][1]; | ||||
|         v = 1; | ||||
| @@ -352,11 +371,12 @@ static int GetCoeffs(VP8BitReader* const br, | ||||
|               v = 7 + 2 * VP8GetBit(br, 165) + VP8GetBit(br, 145); | ||||
|             } | ||||
|           } else { | ||||
|             uint8_t* tab; | ||||
|             const int bit1 = VP8GetBit(br, p[8]); | ||||
|             const int bit0 = VP8GetBit(br, p[9 + bit1]); | ||||
|             const int cat = 2 * bit1 + bit0; | ||||
|             v = 0; | ||||
|             for (const uint8_t* tab = kCat3456[cat]; *tab; ++tab) { | ||||
|             for (tab = (uint8_t*)kCat3456[cat]; *tab; ++tab) { | ||||
|               v += v + VP8GetBit(br, *tab); | ||||
|             } | ||||
|             v += 3 + (8 << cat); | ||||
| @@ -364,7 +384,7 @@ static int GetCoeffs(VP8BitReader* const br, | ||||
|         } | ||||
|         p = prob[kBands[n]][2]; | ||||
|       } | ||||
|       const int j = kZigzag[n - 1]; | ||||
|       j = kZigzag[n - 1]; | ||||
|       out[j] = VP8GetSigned(br, v) * dq[j > 0]; | ||||
|       if (n == 16) break; | ||||
|       if (!VP8GetBit(br, p[0])) {   // EOB | ||||
| @@ -394,6 +414,12 @@ static int ParseResiduals(VP8Decoder* const dec, | ||||
|   const VP8QuantMatrix* q = &dec->dqm_[dec->segment_]; | ||||
|   int16_t* dst = dec->coeffs_; | ||||
|   VP8MB* const left_mb = dec->mb_info_ - 1; | ||||
|   uint8_t nz_ac[4], nz_dc[4]; | ||||
|   uint32_t non_zero_ac = 0; | ||||
|   uint32_t non_zero_dc = 0; | ||||
|   uint8_t tnz[4], lnz[4]; | ||||
|   int x, y, ch; | ||||
|  | ||||
|   memset(dst, 0, 384 * sizeof(*dst)); | ||||
|   if (!dec->is_i4x4_) {    // parse DC | ||||
|     int16_t dc[16] = { 0 }; | ||||
| @@ -409,16 +435,12 @@ static int ParseResiduals(VP8Decoder* const dec, | ||||
|     ac_prob = (Proba_t)dec->proba_.coeffs_[3]; | ||||
|   } | ||||
|  | ||||
|   uint8_t nz_ac[4], nz_dc[4]; | ||||
|   uint32_t non_zero_ac = 0; | ||||
|   uint32_t non_zero_dc = 0; | ||||
|  | ||||
|   uint8_t tnz[4], lnz[4]; | ||||
|   memcpy(tnz, kUnpackTab[mb->nz_ & 0xf], sizeof(tnz)); | ||||
|   memcpy(lnz, kUnpackTab[left_mb->nz_ & 0xf], sizeof(lnz)); | ||||
|   for (int y = 0; y < 4; ++y) { | ||||
|   for (y = 0; y < 4; ++y) { | ||||
|     int l = lnz[y]; | ||||
|     for (int x = 0; x < 4; ++x) { | ||||
|  | ||||
|     for (x = 0; x < 4; ++x) { | ||||
|       const int ctx = l + tnz[x]; | ||||
|       const int last = GetCoeffs(token_br, ac_prob, ctx, | ||||
|                                  q->y1_mat_, first, dst); | ||||
| @@ -436,10 +458,10 @@ static int ParseResiduals(VP8Decoder* const dec, | ||||
|  | ||||
|   memcpy(tnz, kUnpackTab[mb->nz_ >> 4], sizeof(tnz)); | ||||
|   memcpy(lnz, kUnpackTab[left_mb->nz_ >> 4], sizeof(lnz)); | ||||
|   for (int ch = 0; ch < 4; ch += 2) { | ||||
|     for (int y = 0; y < 2; ++y) { | ||||
|   for (ch = 0; ch < 4; ch += 2) { | ||||
|     for (y = 0; y < 2; ++y) { | ||||
|       int l = lnz[ch + y]; | ||||
|       for (int x = 0; x < 2; ++x) { | ||||
|       for (x = 0; x < 2; ++x) { | ||||
|         const int ctx = l + tnz[ch + x]; | ||||
|         const int last = | ||||
|             GetCoeffs(token_br, (Proba_t)dec->proba_.coeffs_[2], | ||||
| @@ -485,13 +507,17 @@ static void SendBlock(VP8Decoder* const dec, VP8Io* io) { | ||||
| static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { | ||||
|   int ok = 1; | ||||
|   VP8BitReader* const br = &dec->br_; | ||||
|   VP8BitReader* token_br; | ||||
|  | ||||
|   for (dec->mb_y_ = 0; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { | ||||
|     memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); | ||||
|     VP8MB* const left = dec->mb_info_ - 1; | ||||
|  | ||||
|     memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); | ||||
|  | ||||
|     left->nz_ = 0; | ||||
|     left->dc_nz_ = 0; | ||||
|     VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; | ||||
|     token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; | ||||
|  | ||||
|     for (dec->mb_x_ = 0; dec->mb_x_ < dec->mb_w_;  dec->mb_x_++) { | ||||
|       VP8MB* const info = dec->mb_info_ + dec->mb_x_; | ||||
|  | ||||
|   | ||||
							
								
								
									
										153
									
								
								src/webp.c
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								src/webp.c
									
									
									
									
									
								
							| @@ -35,25 +35,28 @@ static inline uint32_t get_le32(const uint8_t* const data) { | ||||
| } | ||||
|  | ||||
| // If a RIFF container is detected, validate it and skip over it. | ||||
| static int CheckRIFFHeader(const uint8_t** data_ptr, uint32_t *data_size_ptr) { | ||||
| static uint32_t CheckRIFFHeader(const uint8_t** data_ptr, | ||||
|                                 uint32_t *data_size_ptr) { | ||||
|   uint32_t chunk_size = 0xffffffffu; | ||||
|   if (*data_size_ptr >= 10 + 20 && !memcmp(*data_ptr, "RIFF", 4)) { | ||||
|     if (memcmp(*data_ptr + 8, "WEBP", 4)) { | ||||
|       return 0;  // wrong image file signature | ||||
|     } else { | ||||
|       const uint32_t riff_size = get_le32(*data_ptr + 4); | ||||
|       if (memcmp(*data_ptr + 12, "VP8 ", 4)) { | ||||
|         return 0;   // invalid compression format | ||||
|       } | ||||
|       chunk_size = get_le32(*data_ptr + 16); | ||||
|       if ((chunk_size > riff_size + 8) || (chunk_size & 1)) { | ||||
|         return 0;  // inconsistent size information. | ||||
|       } | ||||
|       // We have a IFF container. Skip it. | ||||
|       *data_ptr += 20; | ||||
|       *data_size_ptr -= 20; | ||||
|     } | ||||
|     const uint32_t riff_size = get_le32(*data_ptr + 4); | ||||
|     if (memcmp(*data_ptr + 12, "VP8 ", 4)) { | ||||
|       return 0;   // invalid compression format | ||||
|     } | ||||
|     chunk_size = get_le32(*data_ptr + 16); | ||||
|     if ((chunk_size > riff_size + 8) || (chunk_size & 1)) { | ||||
|       return 0;  // inconsistent size information. | ||||
|     } | ||||
|     // We have a IFF container. Skip it. | ||||
|     *data_ptr += 20; | ||||
|     *data_size_ptr -= 20; | ||||
|     return chunk_size; | ||||
|   } | ||||
|   return chunk_size; | ||||
|   return *data_size_ptr; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| @@ -75,24 +78,32 @@ static void CustomPut(const VP8Io* io) { | ||||
|   Params *p = (Params*)io->opaque; | ||||
|   const int mb_w = io->mb_w; | ||||
|   const int mb_h = io->mb_h; | ||||
|   int j; | ||||
|  | ||||
|   if (p->mode == MODE_YUV) { | ||||
|     uint8_t* const y_dst = p->output + io->mb_x + io->mb_y * p->stride; | ||||
|     for (int j = 0; j < mb_h; ++j) { | ||||
|     uint8_t* u_dst; | ||||
|     uint8_t* v_dst; | ||||
|     int uv_w; | ||||
|  | ||||
|     for (j = 0; j < mb_h; ++j) { | ||||
|       memcpy(y_dst + j * p->stride, io->y + j * io->y_stride, mb_w); | ||||
|     } | ||||
|     uint8_t* const u_dst = p->u + (io->mb_x / 2) + (io->mb_y / 2) * p->u_stride; | ||||
|     uint8_t* const v_dst = p->v + (io->mb_x / 2) + (io->mb_y / 2) * p->v_stride; | ||||
|     const int uv_w = (mb_w + 1) / 2; | ||||
|     for (int j = 0; j < (mb_h + 1) / 2; ++j) { | ||||
|     u_dst = p->u + (io->mb_x / 2) + (io->mb_y / 2) * p->u_stride; | ||||
|     v_dst = p->v + (io->mb_x / 2) + (io->mb_y / 2) * p->v_stride; | ||||
|     uv_w = (mb_w + 1) / 2; | ||||
|     for (j = 0; j < (mb_h + 1) / 2; ++j) { | ||||
|       memcpy(u_dst + j * p->u_stride, io->u + j * io->uv_stride, uv_w); | ||||
|       memcpy(v_dst + j * p->v_stride, io->v + j * io->uv_stride, uv_w); | ||||
|     } | ||||
|   } else { | ||||
|     const int psize = (p->mode == MODE_RGB || p->mode == MODE_BGR) ? 3 : 4; | ||||
|     uint8_t* dst = p->output + psize * io->mb_x + io->mb_y * p->stride; | ||||
|     for (int j = 0; j < mb_h; ++j) { | ||||
|     int i; | ||||
|  | ||||
|     for (j = 0; j < mb_h; ++j) { | ||||
|       const uint8_t* y_src = io->y + j * io->y_stride; | ||||
|       for (int i = 0; i < mb_w; ++i) { | ||||
|       for (i = 0; i < mb_w; ++i) { | ||||
|         const int y = y_src[i]; | ||||
|         const int u = io->u[(j / 2) * io->uv_stride + (i / 2)]; | ||||
|         const int v = io->v[(j / 2) * io->uv_stride + (i / 2)]; | ||||
| @@ -120,11 +131,13 @@ static uint8_t* DecodeInto(CSP_MODE mode, | ||||
|                            Params* params, int output_size, | ||||
|                            int output_u_size, int output_v_size) { | ||||
|   VP8Decoder* dec = VP8New(); | ||||
|   VP8Io io; | ||||
|   int ok = 1; | ||||
|  | ||||
|   if (dec == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   VP8Io io; | ||||
|   VP8InitIo(&io); | ||||
|   io.data = data; | ||||
|   io.data_size = data_size; | ||||
| @@ -138,17 +151,17 @@ static uint8_t* DecodeInto(CSP_MODE mode, | ||||
|     return NULL; | ||||
|   } | ||||
|   // check output buffers | ||||
|   int ok = 1; | ||||
|  | ||||
|   ok &= (params->stride * io.height <= output_size); | ||||
|   if (mode == MODE_RGB || mode == MODE_BGR) { | ||||
|     ok &= (params->stride >= io.width * 3); | ||||
|   } else if (mode == MODE_RGBA || mode == MODE_BGRA) { | ||||
|     ok &= (params->stride >= io.width * 4); | ||||
|   } else { | ||||
|     ok &= (params->stride >= io.width); | ||||
|     // some extra checks for U/V | ||||
|     const int u_size = params->u_stride * ((io.height + 1) / 2); | ||||
|     const int v_size = params->v_stride * ((io.height + 1) / 2); | ||||
|     ok &= (params->stride >= io.width); | ||||
|     ok &= (params->u_stride >= (io.width + 1) / 2) && | ||||
|           (params->v_stride >= (io.width + 1) / 2); | ||||
|     ok &= (u_size <= output_u_size && v_size <= output_v_size); | ||||
| @@ -170,10 +183,12 @@ static uint8_t* DecodeInto(CSP_MODE mode, | ||||
| uint8_t* WebPDecodeRGBInto(const uint8_t* data, uint32_t data_size, | ||||
|                            uint8_t* output, int output_size, | ||||
|                            int output_stride) { | ||||
|   Params params; | ||||
|  | ||||
|   if (output == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
|   Params params; | ||||
|  | ||||
|   params.output = output; | ||||
|   params.stride = output_stride; | ||||
|   return DecodeInto(MODE_RGB, data, data_size, ¶ms, output_size, 0, 0); | ||||
| @@ -182,10 +197,12 @@ uint8_t* WebPDecodeRGBInto(const uint8_t* data, uint32_t data_size, | ||||
| uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size, | ||||
|                             uint8_t* output, int output_size, | ||||
|                             int output_stride) { | ||||
|   Params params; | ||||
|  | ||||
|   if (output == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
|   Params params; | ||||
|  | ||||
|   params.output = output; | ||||
|   params.stride = output_stride; | ||||
|   return DecodeInto(MODE_RGBA, data, data_size, ¶ms, output_size, 0, 0); | ||||
| @@ -194,10 +211,12 @@ uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size, | ||||
| uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size, | ||||
|                            uint8_t* output, int output_size, | ||||
|                            int output_stride) { | ||||
|   Params params; | ||||
|  | ||||
|   if (output == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
|   Params params; | ||||
|  | ||||
|   params.output = output; | ||||
|   params.stride = output_stride; | ||||
|   return DecodeInto(MODE_BGR, data, data_size, ¶ms, output_size, 0, 0); | ||||
| @@ -206,10 +225,12 @@ uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size, | ||||
| uint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size, | ||||
|                             uint8_t* output, int output_size, | ||||
|                             int output_stride) { | ||||
|   Params params; | ||||
|  | ||||
|   if (output == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
|   Params params; | ||||
|  | ||||
|   params.output = output; | ||||
|   params.stride = output_stride; | ||||
|   return DecodeInto(MODE_BGRA, data, data_size, ¶ms, output_size, 0, 0); | ||||
| @@ -219,10 +240,12 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size, | ||||
|                            uint8_t* luma, int luma_size, int luma_stride, | ||||
|                            uint8_t* u, int u_size, int u_stride, | ||||
|                            uint8_t* v, int v_size, int v_stride) { | ||||
|   Params params; | ||||
|  | ||||
|   if (luma == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
|   Params params; | ||||
|  | ||||
|   params.output = luma; | ||||
|   params.stride = luma_stride; | ||||
|   params.u = u; | ||||
| @@ -237,7 +260,13 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size, | ||||
|  | ||||
| static uint8_t* Decode(CSP_MODE mode, const uint8_t* data, uint32_t data_size, | ||||
|                        int* width, int* height, Params* params_out) { | ||||
|   int w, h; | ||||
|   int w, h, stride; | ||||
|   int uv_size = 0; | ||||
|   int uv_stride = 0; | ||||
|   int size; | ||||
|   uint8_t* output; | ||||
|   Params params = { 0 }; | ||||
|  | ||||
|   if (!WebPGetInfo(data, data_size, &w, &h)) { | ||||
|     return NULL; | ||||
|   } | ||||
| @@ -245,21 +274,21 @@ static uint8_t* Decode(CSP_MODE mode, const uint8_t* data, uint32_t data_size, | ||||
|   if (height) *height = h; | ||||
|  | ||||
|   // initialize output buffer, now that dimensions are known. | ||||
|   int stride = (mode == MODE_RGB || mode == MODE_BGR) ? 3 * w | ||||
|   stride = (mode == MODE_RGB || mode == MODE_BGR) ? 3 * w | ||||
|              : (mode == MODE_RGBA || mode == MODE_BGRA) ? 4 * w | ||||
|              : w; | ||||
|   const int size = stride * h; | ||||
|   int uv_size = 0; | ||||
|   int uv_stride = 0; | ||||
|   size = stride * h; | ||||
|  | ||||
|   if (mode == MODE_YUV) { | ||||
|     uv_stride = (w + 1) / 2; | ||||
|     uv_size = uv_stride * ((h + 1) / 2); | ||||
|   } | ||||
|   uint8_t* const output = (uint8_t*)malloc(size + 2 * uv_size); | ||||
|  | ||||
|   output = (uint8_t*)malloc(size + 2 * uv_size); | ||||
|   if (!output) { | ||||
|     return NULL; | ||||
|   } | ||||
|   Params params = { 0 }; | ||||
|  | ||||
|   params.output = output; | ||||
|   params.stride = stride; | ||||
|   if (mode == MODE_YUV) { | ||||
| @@ -325,35 +354,35 @@ int WebPGetInfo(const uint8_t* data, uint32_t data_size, | ||||
|   // check signature | ||||
|   if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a) { | ||||
|     return 0;         // Wrong signature. | ||||
|   } | ||||
|   const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); | ||||
|   const int key_frame = !(bits & 1); | ||||
|   if (!key_frame) {   // Not a keyframe. | ||||
|     return 0; | ||||
|   } | ||||
|   const int profile = (bits >> 1) & 7; | ||||
|   const int show_frame  = (bits >> 4) & 1; | ||||
|   const uint32_t partition_length = (bits >> 5); | ||||
|   if (profile > 3) { | ||||
|     return 0;         // unknown profile | ||||
|   } | ||||
|   if (!show_frame) { | ||||
|     return 0;         // first frame is invisible! | ||||
|   } | ||||
|   if (partition_length >= chunk_size) { | ||||
|     return 0;         // inconsistent size information. | ||||
|   } | ||||
|   } else { | ||||
|     const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); | ||||
|     const int key_frame = !(bits & 1); | ||||
|     const int w = ((data[7] << 8) | data[6]) & 0x3fff; | ||||
|     const int h = ((data[9] << 8) | data[8]) & 0x3fff; | ||||
|  | ||||
|   const int w = ((data[7] << 8) | data[6]) & 0x3fff; | ||||
|   const int h = ((data[9] << 8) | data[8]) & 0x3fff; | ||||
|   if (width) { | ||||
|     *width = w; | ||||
|   } | ||||
|   if (height) { | ||||
|     *height = h; | ||||
|   } | ||||
|     if (!key_frame) {   // Not a keyframe. | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|   return 1; | ||||
|     if (((bits >> 1) & 7) > 3) { | ||||
|       return 0;         // unknown profile | ||||
|     } | ||||
|     if (!((bits >> 4) & 1)) { | ||||
|       return 0;         // first frame is invisible! | ||||
|     } | ||||
|     if (((bits >> 5)) >= chunk_size) { // partition_length | ||||
|       return 0;         // inconsistent size information. | ||||
|     } | ||||
|  | ||||
|     if (width) { | ||||
|       *width = w; | ||||
|     } | ||||
|     if (height) { | ||||
|       *height = h; | ||||
|     } | ||||
|  | ||||
|     return 1; | ||||
|   } | ||||
| } | ||||
|  | ||||
| #if defined(__cplusplus) || defined(c_plusplus) | ||||
|   | ||||
| @@ -24,18 +24,19 @@ uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; | ||||
| static int done = 0; | ||||
|  | ||||
| void VP8YUVInit() { | ||||
|   int i; | ||||
|   if (done) { | ||||
|     return; | ||||
|   } | ||||
|   for (int i = 0; i < 256; ++i) { | ||||
|   for (i = 0; i < 256; ++i) { | ||||
|     VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; | ||||
|     VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; | ||||
|     VP8kVToG[i] = -45773 * (i - 128); | ||||
|     VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX; | ||||
|   } | ||||
|   for (int i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { | ||||
|     const int j = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX; | ||||
|     VP8kClip[i - YUV_RANGE_MIN] = (j < 0) ? 0 : (j > 255) ? 255 : j; | ||||
|   for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { | ||||
|     const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX; | ||||
|     VP8kClip[i - YUV_RANGE_MIN] = (k < 0) ? 0 : (k > 255) ? 255 : k; | ||||
|   } | ||||
|   done = 1; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user