Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than riff_size) VP8/VP8L header, VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and VP8_STATUS_OK otherwise. If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes extracted from the VP8/VP8L chunk header. The flag '*is_lossless'
| 196 | // extracted from the VP8/VP8L chunk header. |
| 197 | // The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. |
| 198 | static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, size_t* const data_size, |
| 199 | int have_all_data, size_t riff_size, size_t* const chunk_size, |
| 200 | int* const is_lossless) { |
| 201 | const uint8_t* const data = *data_ptr; |
| 202 | const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); |
| 203 | const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); |
| 204 | const uint32_t minimal_size = TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR |
| 205 | // "WEBP" + "VP8Lnnnn" |
| 206 | assert(data != nullptr); |
| 207 | assert(data_size != nullptr); |
| 208 | assert(chunk_size != nullptr); |
| 209 | assert(is_lossless != nullptr); |
| 210 | |
| 211 | if (*data_size < CHUNK_HEADER_SIZE) { |
| 212 | return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. |
| 213 | } |
| 214 | |
| 215 | if (is_vp8 || is_vp8l) { |
| 216 | // Bitstream contains VP8/VP8L header. |
| 217 | const uint32_t size = GetLE32(data + TAG_SIZE); |
| 218 | if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { |
| 219 | return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. |
| 220 | } |
| 221 | if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { |
| 222 | return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. |
| 223 | } |
| 224 | // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. |
| 225 | *chunk_size = size; |
| 226 | *data_ptr += CHUNK_HEADER_SIZE; |
| 227 | *data_size -= CHUNK_HEADER_SIZE; |
| 228 | *is_lossless = is_vp8l; |
| 229 | } else { |
| 230 | // Raw VP8/VP8L bitstream (no header). |
| 231 | *is_lossless = VP8LCheckSignature(data, *data_size); |
| 232 | *chunk_size = *data_size; |
| 233 | } |
| 234 | |
| 235 | return VP8_STATUS_OK; |
| 236 | } |
| 237 | |
| 238 | int VP8CheckSignature(const uint8_t* const data, size_t data_size) { |
| 239 | return (data_size >= 3 && data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); |
no test coverage detected