mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 10:25:46 +01:00 
			
		
		
		
	Merge "reorganize chunk-parsing code"
This commit is contained in:
		| @@ -20,9 +20,8 @@ | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #define RIFF_HEADER_SIZE 20 | ||||
| #define RIFF_HEADER_SIZE 12 | ||||
| #define VP8_HEADER_SIZE 10 | ||||
| #define WEBP_HEADER_SIZE (RIFF_HEADER_SIZE + VP8_HEADER_SIZE) | ||||
| #define CHUNK_SIZE 4096 | ||||
| #define MAX_MB_SIZE 4096 | ||||
|  | ||||
| @@ -245,16 +244,40 @@ static VP8StatusCode DecodeHeader(WebPIDecoder* const idec) { | ||||
|   const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; | ||||
|   uint32_t curr_size = MemDataSize(&idec->mem_); | ||||
|   uint32_t chunk_size; | ||||
|   uint32_t riff_size; | ||||
|   int is_vp8x_chunk = 0; | ||||
|   int is_vp8_chunk = 0; | ||||
|  | ||||
|   if (curr_size < WEBP_HEADER_SIZE) { | ||||
|   if (curr_size < RIFF_HEADER_SIZE) { | ||||
|     return VP8_STATUS_SUSPENDED; | ||||
|   } | ||||
|  | ||||
|   // Validate and Skip over RIFF header | ||||
|   chunk_size = WebPCheckRIFFHeader(&data, &curr_size); | ||||
|   if (chunk_size == 0 || | ||||
|       curr_size < VP8_HEADER_SIZE || | ||||
|       !VP8GetInfo(data, curr_size, chunk_size, NULL, NULL, NULL)) { | ||||
|   if (!WebPCheckAndSkipRIFFHeader(&data, &curr_size, &riff_size)) { | ||||
|     return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);  // Wrong RIFF Header. | ||||
|   } | ||||
|  | ||||
|   if (!VP8XGetInfo(&data, &curr_size, &is_vp8x_chunk, NULL, NULL, NULL)) { | ||||
|     return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);  // Wrong VP8X Chunk. | ||||
|   } | ||||
|  | ||||
|   if (is_vp8x_chunk == -1) { | ||||
|     return VP8_STATUS_SUSPENDED;  // Not enough data bytes to process chunk. | ||||
|   } | ||||
|  | ||||
|   if (!VP8CheckAndSkipHeader(&data, &curr_size, &is_vp8_chunk, &chunk_size, | ||||
|                              riff_size)) { | ||||
|     return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);  // Invalid VP8 header. | ||||
|   } | ||||
|  | ||||
|   if ((is_vp8_chunk == -1) && (chunk_size == 0)){ | ||||
|     return VP8_STATUS_SUSPENDED;  // Not enough data bytes to extract chunk_size | ||||
|   } | ||||
|  | ||||
|   if (curr_size < VP8_HEADER_SIZE) { | ||||
|     return VP8_STATUS_SUSPENDED;  // Not enough data bytes to extract VP8 Header | ||||
|   } | ||||
|  | ||||
|   if (!VP8GetInfo(data, curr_size, chunk_size, NULL, NULL, NULL)) { | ||||
|     return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										137
									
								
								src/dec/vp8.c
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								src/dec/vp8.c
									
									
									
									
									
								
							| @@ -11,11 +11,15 @@ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include "vp8i.h" | ||||
| #include "webpi.h" | ||||
|  | ||||
| #if defined(__cplusplus) || defined(c_plusplus) | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #define RIFF_HEADER_SIZE 12 | ||||
| #define VP8X_HEADER_SIZE 20 | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| int WebPGetDecoderVersion(void) { | ||||
| @@ -77,8 +81,40 @@ int VP8SetError(VP8Decoder* const dec, | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| int VP8GetInfo(const uint8_t* data, | ||||
|                uint32_t data_size, uint32_t chunk_size, | ||||
| static inline uint32_t get_le32(const uint8_t* const data) { | ||||
|   return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | ||||
| } | ||||
|  | ||||
| int VP8CheckAndSkipHeader(const uint8_t** data_ptr, uint32_t* data_size_ptr, | ||||
|                           int* is_vp8_chunk, uint32_t* chunk_size, | ||||
|                           uint32_t riff_size) { | ||||
|   if (!data_ptr || !data_size_ptr || !is_vp8_chunk || !chunk_size) { | ||||
|     return 0;  // Invalid Args. | ||||
|   } | ||||
|  | ||||
|   if (*data_size_ptr >= 8) { | ||||
|     if (!memcmp(*data_ptr, "VP8 ", 4)) { | ||||
|       *is_vp8_chunk = 1; | ||||
|       *chunk_size = get_le32(*data_ptr + 4); | ||||
|       if ((riff_size >= RIFF_HEADER_SIZE) && | ||||
|           (*chunk_size > riff_size - RIFF_HEADER_SIZE)) { | ||||
|         return 0;  // Inconsistent size information. | ||||
|       } | ||||
|       // We have consumed 8 bytes from VP8 Header. Skip it. | ||||
|       *data_ptr += 8; | ||||
|       *data_size_ptr -= 8; | ||||
|     } else { | ||||
|       *is_vp8_chunk = 0; | ||||
|       *chunk_size = 0; | ||||
|     } | ||||
|   } else { | ||||
|     *is_vp8_chunk = -1;  // Insufficient data. | ||||
|     *chunk_size = 0; | ||||
|   } | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| int VP8GetInfo(const uint8_t* data, uint32_t data_size, uint32_t chunk_size, | ||||
|                int* width, int* height, int* has_alpha) { | ||||
|   if (data_size < 10) { | ||||
|     return 0;         // not enough data | ||||
| @@ -125,6 +161,40 @@ int VP8GetInfo(const uint8_t* data, | ||||
|   } | ||||
| } | ||||
|  | ||||
| int VP8XGetInfo(const uint8_t** data_ptr, uint32_t* data_size_ptr, | ||||
|                 int* is_vp8x_chunk, int* width, int* height, uint32_t* flags) { | ||||
|   if (!data_ptr || !data_size_ptr || !is_vp8x_chunk) { | ||||
|     return 0;  // Invalid Args. | ||||
|   } | ||||
|  | ||||
|   if (*data_size_ptr >= VP8X_HEADER_SIZE) { | ||||
|     if (!memcmp(*data_ptr, "VP8X", 4)) { | ||||
|       const uint32_t chunk_size = get_le32(*data_ptr + 4); | ||||
|       *is_vp8x_chunk = 1; | ||||
|       if (chunk_size != (VP8X_HEADER_SIZE - 8)) { | ||||
|         return 0;  // Wrong chunk size. | ||||
|       } | ||||
|       if (flags) { | ||||
|         *flags = get_le32(*data_ptr + 8); | ||||
|       } | ||||
|       if (width) { | ||||
|         *width = get_le32(*data_ptr + 12); | ||||
|       } | ||||
|       if (height) { | ||||
|         *height = get_le32(*data_ptr + 16); | ||||
|       } | ||||
|       // We have consumed 20 bytes from VP8X Header. Skip it. | ||||
|       *data_ptr += VP8X_HEADER_SIZE; | ||||
|       *data_size_ptr -= VP8X_HEADER_SIZE; | ||||
|     } else { | ||||
|       *is_vp8x_chunk = 0; | ||||
|     } | ||||
|   } else { | ||||
|     *is_vp8x_chunk = -1;  // Insufficient data. | ||||
|   } | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Header parsing | ||||
|  | ||||
| @@ -245,14 +315,14 @@ static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { | ||||
|   return !br->eof_; | ||||
| } | ||||
|  | ||||
| static inline uint32_t get_le32(const uint8_t* const data) { | ||||
|   return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | ||||
| } | ||||
|  | ||||
| // Topmost call | ||||
| int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|   uint8_t* buf; | ||||
|   const uint8_t* buf; | ||||
|   uint32_t buf_size; | ||||
|   uint32_t riff_size; | ||||
|   uint32_t chunk_size; | ||||
|   int is_vp8x_chunk = 0; | ||||
|   int is_vp8_chunk = 0; | ||||
|   VP8FrameHeader* frm_hdr; | ||||
|   VP8PictureHeader* pic_hdr; | ||||
|   VP8BitReader* br; | ||||
| @@ -274,34 +344,31 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|                        "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, VP8_STATUS_NOT_ENOUGH_DATA, | ||||
|                          "RIFF: Truncated header."); | ||||
|     } | ||||
|     if (memcmp(buf + 8, "WEBP", 4)) {   // wrong image file signature | ||||
|   // Skip over valid RIFF headers. | ||||
|   if (!WebPCheckAndSkipRIFFHeader(&buf, &buf_size, &riff_size)) { | ||||
|     return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | ||||
|                        "RIFF: Invalid RIFF container"); | ||||
|   } | ||||
|  | ||||
|   if (!VP8XGetInfo(&buf, &buf_size, &is_vp8x_chunk, NULL, NULL, NULL)) { | ||||
|     return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | ||||
|                        "RIFF: Invalid VP8X container"); | ||||
|   } | ||||
|  | ||||
|   if (!VP8CheckAndSkipHeader(&buf, &buf_size, &is_vp8_chunk, &chunk_size, | ||||
|                              riff_size)) { | ||||
|     return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | ||||
|                        "RIFF: Inconsistent size information."); | ||||
|   } | ||||
|  | ||||
|   if (is_vp8_chunk == -1) { | ||||
|       return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | ||||
|                          "RIFF: WEBP signature not found."); | ||||
|     } | ||||
|     riff_size = get_le32(buf + 4); | ||||
|     if (riff_size < 12) { | ||||
|       return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, | ||||
|                          "RIFF: Truncated header."); | ||||
|     } | ||||
|     if (memcmp(buf + 12, "VP8 ", 4)) { | ||||
|       return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | ||||
|                          "RIFF: Invalid compression format."); | ||||
|     } | ||||
|     chunk_size = get_le32(buf + 16); | ||||
|     if (chunk_size > riff_size - 12) { | ||||
|       return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | ||||
|                          "RIFF: Inconsistent size information."); | ||||
|     } | ||||
|     buf += 20; | ||||
|     buf_size -= 20; | ||||
|                          "Not enough data to parse frame header."); | ||||
|   } | ||||
|  | ||||
|   if (buf_size < 4) { | ||||
|     return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, | ||||
|                        "RIFF: Truncated header."); | ||||
|   } | ||||
|  | ||||
|   // Paragraph 9.1 | ||||
| @@ -437,7 +504,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | ||||
|   if (dec->pic_hdr_.colorspace_) { | ||||
|     const size_t kTrailerSize = 8; | ||||
|     const uint8_t kTrailerMarker = 0x01; | ||||
|     uint8_t* const ext_buf = buf - kTrailerSize; | ||||
|     const uint8_t* ext_buf = buf - kTrailerSize; | ||||
|     size_t size; | ||||
|  | ||||
|     if (frm_hdr->partition_length_ < kTrailerSize || | ||||
|   | ||||
| @@ -286,6 +286,20 @@ struct VP8Decoder { | ||||
| // in vp8.c | ||||
| int VP8SetError(VP8Decoder* const dec, | ||||
|                 VP8StatusCode error, const char * const msg); | ||||
|  | ||||
| // Validates the VP8 Header and skip over it. | ||||
| // Returns 0 for invalid (chunk_size greater than riff_size) VP8 header. | ||||
| // Else return 1. | ||||
| // is_vp8_chunk is set to: | ||||
| //   0, in case data bytes don't correspond to VP8 chunk. | ||||
| //   1, in case data bytes correspond to VP8 chunk. | ||||
| //   -1, in case not enough bytes (partial VP8 chunk) are passed. | ||||
| // chunk_size is set to the chunk size extracted from the VP8 chunk header. For | ||||
| // partial VP8 chunk, chunk_size is set to 0. | ||||
| int VP8CheckAndSkipHeader(const uint8_t** data_ptr, uint32_t* data_size_ptr, | ||||
|                           int* is_vp8_chunk, uint32_t* chunk_size, | ||||
|                           uint32_t riff_size); | ||||
|  | ||||
| // Validates the VP8 data-header and retrieve basic header information viz width | ||||
| // and height. Returns 0 in case of formatting error. *width/*height/*has_alpha | ||||
| // can be passed NULL. | ||||
| @@ -294,6 +308,17 @@ int VP8GetInfo(const uint8_t* data, | ||||
|                uint32_t chunk_size,   // total data size expect in the chunk | ||||
|                int *width, int *height, int *has_alpha); | ||||
|  | ||||
| // Validates the VP8X Header and skip over it. | ||||
| // Returns 0 for invalid VP8X header. Else return 1. | ||||
| // is_vp8x_chunk is set to: | ||||
| //   0, in case data bytes doesn't correspond to VP8X chunk. | ||||
| //   1, in case data bytes correspond to VP8X chunk. | ||||
| //   -1, in case not enough bytes (partial VP8X chunk) are passed. | ||||
| // Width, Height & Flags are set to the corresponding fields extracted from the | ||||
| // VP8X chunk. | ||||
| int VP8XGetInfo(const uint8_t** data_ptr, uint32_t* data_size_ptr, | ||||
|                 int* is_vp8x_chunk, int* width, int* height, uint32_t* flags); | ||||
|  | ||||
| // in tree.c | ||||
| void VP8ResetProba(VP8Proba* const proba); | ||||
| void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec); | ||||
|   | ||||
							
								
								
									
										119
									
								
								src/dec/webp.c
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								src/dec/webp.c
									
									
									
									
									
								
							| @@ -17,16 +17,26 @@ | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #define RIFF_HEADER_SIZE 12 | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // RIFF layout is: | ||||
| //   0ffset  tag | ||||
| //   0...3   "RIFF" 4-byte tag | ||||
| //   4...7   size of image data (including metadata) starting at offset 8 | ||||
| //   8...11  "WEBP"   our form-type signature | ||||
| // The RIFF container (12 bytes) is followed by appropriate chunks: | ||||
| //   12..15  "VP8 ": 4-bytes tags, describing the raw video format used | ||||
| //   16..19  size of the raw VP8 image data, starting at offset 20 | ||||
| //   20....  the VP8 bytes | ||||
| // There can be extra chunks after the "VP8 " chunk (ICMT, ICOP, ...) | ||||
| // Or, | ||||
| //   12..15  "VP8X": 4-bytes tags, describing the extended-VP8 chunk. | ||||
| //   16..19  size of the VP8X chunk starting at offset 8. | ||||
| //   20..23  VP8X flags bit-map corresponding to the chunk-types present. | ||||
| //   24..27  Width of the Canvas Image. | ||||
| //   28..31  Height of the Canvas Image. | ||||
| // There can be extra chunks after the "VP8X" chunk (ICCP, TILE, FRM, VP8, | ||||
| // META  ...) | ||||
| // All 32-bits sizes are in little-endian order. | ||||
| // Note: chunk data must be padded to multiple of 2 in size | ||||
|  | ||||
| @@ -34,33 +44,25 @@ static inline uint32_t get_le32(const uint8_t* const data) { | ||||
|   return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | ||||
| } | ||||
|  | ||||
| // If a RIFF container is detected, validate it and skip over it. | ||||
| uint32_t WebPCheckRIFFHeader(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)) { | ||||
| uint32_t WebPCheckAndSkipRIFFHeader(const uint8_t** data_ptr, | ||||
|                                     uint32_t* data_size_ptr, | ||||
|                                     uint32_t* riff_size) { | ||||
|   if (*data_size_ptr >= RIFF_HEADER_SIZE && !memcmp(*data_ptr, "RIFF", 4)) { | ||||
|     if (memcmp(*data_ptr + 8, "WEBP", 4)) { | ||||
|       return 0;  // wrong image file signature | ||||
|       return 0;  // Wrong image file signature. | ||||
|     } else { | ||||
|       const uint32_t riff_size = get_le32(*data_ptr + 4); | ||||
|       if (riff_size < 12) { | ||||
|         return 0;   // we should have at least one chunk | ||||
|       } | ||||
|       if (memcmp(*data_ptr + 12, "VP8 ", 4)) { | ||||
|         return 0;   // invalid compression format | ||||
|       } | ||||
|       chunk_size = get_le32(*data_ptr + 16); | ||||
|       if (chunk_size > riff_size - 12) { | ||||
|         return 0;  // inconsistent size information. | ||||
|       *riff_size = get_le32(*data_ptr + 4); | ||||
|       if (*riff_size < RIFF_HEADER_SIZE) { | ||||
|         return 0;   // We should have at least one chunk. | ||||
|       } | ||||
|       // We have a RIFF container. Skip it. | ||||
|       *data_ptr += 20; | ||||
|       *data_size_ptr -= 20; | ||||
|       // Note: we don't report error for odd-sized chunks. | ||||
|       *data_ptr += RIFF_HEADER_SIZE; | ||||
|       *data_size_ptr -= RIFF_HEADER_SIZE; | ||||
|     } | ||||
|     return chunk_size; | ||||
|   } else { | ||||
|     *riff_size = 0;  // Did not get full RIFF Header. | ||||
|   } | ||||
|   return *data_size_ptr; | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| @@ -268,19 +270,6 @@ uint8_t* WebPDecodeYUV(const uint8_t* data, uint32_t data_size, | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // WebPGetInfo() | ||||
|  | ||||
| int WebPGetInfo(const uint8_t* data, uint32_t data_size, | ||||
|                 int* width, int* height) { | ||||
|   const uint32_t chunk_size = WebPCheckRIFFHeader(&data, &data_size); | ||||
|   if (!chunk_size) { | ||||
|     return 0;         // unsupported RIFF header | ||||
|   } | ||||
|   // Validate raw video data | ||||
|   return VP8GetInfo(data, data_size, chunk_size, width, height, NULL); | ||||
| } | ||||
|  | ||||
| static void DefaultFeatures(WebPBitstreamFeatures* const features) { | ||||
|   assert(features); | ||||
|   memset(features, 0, sizeof(*features)); | ||||
| @@ -289,25 +278,77 @@ static void DefaultFeatures(WebPBitstreamFeatures* const features) { | ||||
|  | ||||
| static VP8StatusCode GetFeatures(const uint8_t** data, uint32_t* data_size, | ||||
|                                  WebPBitstreamFeatures* const features) { | ||||
|   uint32_t chunk_size; | ||||
|   uint32_t chunk_size = 0; | ||||
|   uint32_t riff_size = 0; | ||||
|   uint32_t flags = 0; | ||||
|   int is_vp8x_chunk = 0; | ||||
|   int is_vp8_chunk = 0; | ||||
|  | ||||
|   if (features == NULL) { | ||||
|     return VP8_STATUS_INVALID_PARAM; | ||||
|   } | ||||
|   DefaultFeatures(features); | ||||
|  | ||||
|   if (data == NULL || *data == NULL || data_size == 0) { | ||||
|     return VP8_STATUS_INVALID_PARAM; | ||||
|   } | ||||
|   chunk_size = WebPCheckRIFFHeader(data, data_size); | ||||
|   if (chunk_size == 0) { | ||||
|     return VP8_STATUS_BITSTREAM_ERROR;   // unsupported RIFF header | ||||
|  | ||||
|   if (!WebPCheckAndSkipRIFFHeader(data, data_size, &riff_size)) { | ||||
|     return VP8_STATUS_BITSTREAM_ERROR;   // Wrong RIFF Header. | ||||
|   } | ||||
|  | ||||
|   if (!VP8XGetInfo(data, data_size, &is_vp8x_chunk, | ||||
|                    &features->width, &features->height, &flags)) { | ||||
|     return VP8_STATUS_BITSTREAM_ERROR;  // Wrong VP8X Chunk-header. | ||||
|   } | ||||
|  | ||||
|   if (is_vp8x_chunk > 0) { | ||||
|     return VP8_STATUS_OK; | ||||
|   } | ||||
|  | ||||
|   if (!VP8CheckAndSkipHeader(data, data_size, &is_vp8_chunk, &chunk_size, | ||||
|                              riff_size)) { | ||||
|     return VP8_STATUS_BITSTREAM_ERROR;  // Invalid VP8 header. | ||||
|   } | ||||
|  | ||||
|   if (is_vp8_chunk == -1) { | ||||
|     return VP8_STATUS_BITSTREAM_ERROR;   // Insufficient data-bytes. | ||||
|   } | ||||
|  | ||||
|   if (!is_vp8_chunk) { | ||||
|     chunk_size = *data_size;  // No VP8 chunk wrapper over raw VP8 data. | ||||
|   } | ||||
|  | ||||
|   // Validates raw VP8 data. | ||||
|   if (!VP8GetInfo(*data, *data_size, chunk_size, | ||||
|                   &features->width, &features->height, &features->has_alpha)) { | ||||
|     return VP8_STATUS_BITSTREAM_ERROR; | ||||
|   } | ||||
|  | ||||
|   return VP8_STATUS_OK; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // WebPGetInfo() | ||||
|  | ||||
| int WebPGetInfo(const uint8_t* data, uint32_t data_size, | ||||
|                 int* width, int* height) { | ||||
|   WebPBitstreamFeatures features; | ||||
|  | ||||
|   if (GetFeatures(&data, &data_size, &features) != VP8_STATUS_OK) { | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   if (width) { | ||||
|     *width  = features.width; | ||||
|   } | ||||
|   if (height) { | ||||
|     *height = features.height; | ||||
|   } | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Advance decoding API | ||||
|  | ||||
|   | ||||
| @@ -76,10 +76,13 @@ void WebPInitUpsamplersSSE2(void); | ||||
| //------------------------------------------------------------------------------ | ||||
| // Misc utils | ||||
|  | ||||
| // If a RIFF container is detected, validate it and skip over it. Returns | ||||
| // VP8 bit-stream size if RIFF header is valid else returns 0 | ||||
| uint32_t WebPCheckRIFFHeader(const uint8_t** data_ptr, | ||||
|                              uint32_t* data_size_ptr); | ||||
| // Validates the RIFF container (if detected) and skip over it. | ||||
| // If a RIFF container is detected, returns 0 for invalid header. Else return 1. | ||||
| // In case there are not enough bytes (partial RIFF container), return 0 for | ||||
| // riff_size. Else return the riff_size extracted from the header. | ||||
| uint32_t WebPCheckAndSkipRIFFHeader(const uint8_t** data_ptr, | ||||
|                                     uint32_t* data_size_ptr, | ||||
|                                     uint32_t* riff_size_ptr); | ||||
|  | ||||
| // Initializes VP8Io with custom setup, io and teardown functions. The default | ||||
| // hooks will use the supplied 'params' as io->opaque handle. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user