idec_dec.c (31958B)
1 // Copyright 2011 Google Inc. All Rights Reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the COPYING file in the root of the source 5 // tree. An additional intellectual property rights grant can be found 6 // in the file PATENTS. All contributing project authors may 7 // be found in the AUTHORS file in the root of the source tree. 8 // ----------------------------------------------------------------------------- 9 // 10 // Incremental decoding 11 // 12 // Author: somnath@google.com (Somnath Banerjee) 13 14 #include <assert.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include "src/dec/alphai_dec.h" 19 #include "src/dec/vp8_dec.h" 20 #include "src/dec/vp8i_dec.h" 21 #include "src/dec/vp8li_dec.h" 22 #include "src/dec/webpi_dec.h" 23 #include "src/utils/bit_reader_utils.h" 24 #include "src/utils/thread_utils.h" 25 #include "src/utils/utils.h" 26 #include "src/webp/decode.h" 27 #include "src/webp/format_constants.h" 28 #include "src/webp/types.h" 29 30 // In append mode, buffer allocations increase as multiples of this value. 31 // Needs to be a power of 2. 32 #define CHUNK_SIZE 4096 33 #define MAX_MB_SIZE 4096 34 35 //------------------------------------------------------------------------------ 36 // Data structures for memory and states 37 38 // Decoding states. State normally flows as: 39 // WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and 40 // WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. 41 // If there is any error the decoder goes into state ERROR. 42 typedef enum { 43 STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. 44 STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). 45 STATE_VP8_PARTS0, 46 STATE_VP8_DATA, 47 STATE_VP8L_HEADER, 48 STATE_VP8L_DATA, 49 STATE_DONE, 50 STATE_ERROR 51 } DecState; 52 53 // Operating state for the MemBuffer 54 typedef enum { 55 MEM_MODE_NONE = 0, 56 MEM_MODE_APPEND, 57 MEM_MODE_MAP 58 } MemBufferMode; 59 60 // storage for partition #0 and partial data (in a rolling fashion) 61 typedef struct { 62 MemBufferMode mode; // Operation mode 63 size_t start; // start location of the data to be decoded 64 size_t end; // end location 65 size_t buf_size; // size of the allocated buffer 66 uint8_t* buf; // We don't own this buffer in case WebPIUpdate() 67 68 size_t part0_size; // size of partition #0 69 const uint8_t* part0_buf; // buffer to store partition #0 70 } MemBuffer; 71 72 struct WebPIDecoder { 73 DecState state; // current decoding state 74 WebPDecParams params; // Params to store output info 75 int is_lossless; // for down-casting 'dec'. 76 void* dec; // either a VP8Decoder or a VP8LDecoder instance 77 VP8Io io; 78 79 MemBuffer mem; // input memory buffer. 80 WebPDecBuffer output; // output buffer (when no external one is supplied, 81 // or if the external one has slow-memory) 82 WebPDecBuffer* final_output; // Slow-memory output to copy to eventually. 83 size_t chunk_size; // Compressed VP8/VP8L size extracted from Header. 84 85 int last_mb_y; // last row reached for intra-mode decoding 86 }; 87 88 // MB context to restore in case VP8DecodeMB() fails 89 typedef struct { 90 VP8MB left; 91 VP8MB info; 92 VP8BitReader token_br; 93 } MBContext; 94 95 //------------------------------------------------------------------------------ 96 // MemBuffer: incoming data handling 97 98 static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { 99 return (mem->end - mem->start); 100 } 101 102 // Check if we need to preserve the compressed alpha data, as it may not have 103 // been decoded yet. 104 static int NeedCompressedAlpha(const WebPIDecoder* const idec) { 105 if (idec->state == STATE_WEBP_HEADER) { 106 // We haven't parsed the headers yet, so we don't know whether the image is 107 // lossy or lossless. This also means that we haven't parsed the ALPH chunk. 108 return 0; 109 } 110 if (idec->is_lossless) { 111 return 0; // ALPH chunk is not present for lossless images. 112 } else { 113 const VP8Decoder* const dec = (VP8Decoder*)idec->dec; 114 assert(dec != NULL); // Must be true as idec->state != STATE_WEBP_HEADER. 115 return (dec->alpha_data != NULL) && !dec->is_alpha_decoded; 116 } 117 } 118 119 static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { 120 MemBuffer* const mem = &idec->mem; 121 const uint8_t* const new_base = mem->buf + mem->start; 122 // note: for VP8, setting up idec->io is only really needed at the beginning 123 // of the decoding, till partition #0 is complete. 124 idec->io.data = new_base; 125 idec->io.data_size = MemDataSize(mem); 126 127 if (idec->dec != NULL) { 128 if (!idec->is_lossless) { 129 VP8Decoder* const dec = (VP8Decoder*)idec->dec; 130 const uint32_t last_part = dec->num_parts_minus_one; 131 if (offset != 0) { 132 uint32_t p; 133 for (p = 0; p <= last_part; ++p) { 134 VP8RemapBitReader(dec->parts + p, offset); 135 } 136 // Remap partition #0 data pointer to new offset, but only in MAP 137 // mode (in APPEND mode, partition #0 is copied into a fixed memory). 138 if (mem->mode == MEM_MODE_MAP) { 139 VP8RemapBitReader(&dec->br, offset); 140 } 141 } 142 { 143 const uint8_t* const last_start = dec->parts[last_part].buf; 144 // 'last_start' will be NULL when 'idec->state' is < STATE_VP8_PARTS0 145 // and through a portion of that state (when there isn't enough data to 146 // parse the partitions). The bitreader is only used meaningfully when 147 // there is enough data to begin parsing partition 0. 148 if (last_start != NULL) { 149 VP8BitReaderSetBuffer(&dec->parts[last_part], last_start, 150 mem->buf + mem->end - last_start); 151 } 152 } 153 if (NeedCompressedAlpha(idec)) { 154 ALPHDecoder* const alph_dec = dec->alph_dec; 155 dec->alpha_data += offset; 156 if (alph_dec != NULL && alph_dec->vp8l_dec != NULL) { 157 if (alph_dec->method == ALPHA_LOSSLESS_COMPRESSION) { 158 VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec; 159 assert(dec->alpha_data_size >= ALPHA_HEADER_LEN); 160 VP8LBitReaderSetBuffer(&alph_vp8l_dec->br, 161 dec->alpha_data + ALPHA_HEADER_LEN, 162 dec->alpha_data_size - ALPHA_HEADER_LEN); 163 } else { // alph_dec->method == ALPHA_NO_COMPRESSION 164 // Nothing special to do in this case. 165 } 166 } 167 } 168 } else { // Resize lossless bitreader 169 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec; 170 VP8LBitReaderSetBuffer(&dec->br, new_base, MemDataSize(mem)); 171 } 172 } 173 } 174 175 // Appends data to the end of MemBuffer->buf. It expands the allocated memory 176 // size if required and also updates VP8BitReader's if new memory is allocated. 177 WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec, 178 const uint8_t* const data, 179 size_t data_size) { 180 VP8Decoder* const dec = (VP8Decoder*)idec->dec; 181 MemBuffer* const mem = &idec->mem; 182 const int need_compressed_alpha = NeedCompressedAlpha(idec); 183 const uint8_t* const old_start = 184 (mem->buf == NULL) ? NULL : mem->buf + mem->start; 185 const uint8_t* const old_base = 186 need_compressed_alpha ? dec->alpha_data : old_start; 187 assert(mem->buf != NULL || mem->start == 0); 188 assert(mem->mode == MEM_MODE_APPEND); 189 if (data_size > MAX_CHUNK_PAYLOAD) { 190 // security safeguard: trying to allocate more than what the format 191 // allows for a chunk should be considered a smoke smell. 192 return 0; 193 } 194 195 if (mem->end + data_size > mem->buf_size) { // Need some free memory 196 const size_t new_mem_start = old_start - old_base; 197 const size_t current_size = MemDataSize(mem) + new_mem_start; 198 const uint64_t new_size = (uint64_t)current_size + data_size; 199 const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); 200 uint8_t* const new_buf = 201 (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); 202 if (new_buf == NULL) return 0; 203 if (old_base != NULL) memcpy(new_buf, old_base, current_size); 204 WebPSafeFree(mem->buf); 205 mem->buf = new_buf; 206 mem->buf_size = (size_t)extra_size; 207 mem->start = new_mem_start; 208 mem->end = current_size; 209 } 210 211 assert(mem->buf != NULL); 212 memcpy(mem->buf + mem->end, data, data_size); 213 mem->end += data_size; 214 assert(mem->end <= mem->buf_size); 215 216 DoRemap(idec, mem->buf + mem->start - old_start); 217 return 1; 218 } 219 220 WEBP_NODISCARD static int RemapMemBuffer(WebPIDecoder* const idec, 221 const uint8_t* const data, 222 size_t data_size) { 223 MemBuffer* const mem = &idec->mem; 224 const uint8_t* const old_buf = mem->buf; 225 const uint8_t* const old_start = 226 (old_buf == NULL) ? NULL : old_buf + mem->start; 227 assert(old_buf != NULL || mem->start == 0); 228 assert(mem->mode == MEM_MODE_MAP); 229 230 if (data_size < mem->buf_size) return 0; // can't remap to a shorter buffer! 231 232 mem->buf = (uint8_t*)data; 233 mem->end = mem->buf_size = data_size; 234 235 DoRemap(idec, mem->buf + mem->start - old_start); 236 return 1; 237 } 238 239 static void InitMemBuffer(MemBuffer* const mem) { 240 mem->mode = MEM_MODE_NONE; 241 mem->buf = NULL; 242 mem->buf_size = 0; 243 mem->part0_buf = NULL; 244 mem->part0_size = 0; 245 } 246 247 static void ClearMemBuffer(MemBuffer* const mem) { 248 assert(mem); 249 if (mem->mode == MEM_MODE_APPEND) { 250 WebPSafeFree(mem->buf); 251 WebPSafeFree((void*)mem->part0_buf); 252 } 253 } 254 255 WEBP_NODISCARD static int CheckMemBufferMode(MemBuffer* const mem, 256 MemBufferMode expected) { 257 if (mem->mode == MEM_MODE_NONE) { 258 mem->mode = expected; // switch to the expected mode 259 } else if (mem->mode != expected) { 260 return 0; // we mixed the modes => error 261 } 262 assert(mem->mode == expected); // mode is ok 263 return 1; 264 } 265 266 // To be called last. 267 WEBP_NODISCARD static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { 268 const WebPDecoderOptions* const options = idec->params.options; 269 WebPDecBuffer* const output = idec->params.output; 270 271 idec->state = STATE_DONE; 272 if (options != NULL && options->flip) { 273 const VP8StatusCode status = WebPFlipBuffer(output); 274 if (status != VP8_STATUS_OK) return status; 275 } 276 if (idec->final_output != NULL) { 277 const VP8StatusCode status = WebPCopyDecBufferPixels( 278 output, idec->final_output); // do the slow-copy 279 WebPFreeDecBuffer(&idec->output); 280 if (status != VP8_STATUS_OK) return status; 281 *output = *idec->final_output; 282 idec->final_output = NULL; 283 } 284 return VP8_STATUS_OK; 285 } 286 287 //------------------------------------------------------------------------------ 288 // Macroblock-decoding contexts 289 290 static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, 291 MBContext* const context) { 292 context->left = dec->mb_info[-1]; 293 context->info = dec->mb_info[dec->mb_x]; 294 context->token_br = *token_br; 295 } 296 297 static void RestoreContext(const MBContext* context, VP8Decoder* const dec, 298 VP8BitReader* const token_br) { 299 dec->mb_info[-1] = context->left; 300 dec->mb_info[dec->mb_x] = context->info; 301 *token_br = context->token_br; 302 } 303 304 //------------------------------------------------------------------------------ 305 306 static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { 307 if (idec->state == STATE_VP8_DATA) { 308 // Synchronize the thread, clean-up and check for errors. 309 (void)VP8ExitCritical((VP8Decoder*)idec->dec, &idec->io); 310 } 311 idec->state = STATE_ERROR; 312 return error; 313 } 314 315 static void ChangeState(WebPIDecoder* const idec, DecState new_state, 316 size_t consumed_bytes) { 317 MemBuffer* const mem = &idec->mem; 318 idec->state = new_state; 319 mem->start += consumed_bytes; 320 assert(mem->start <= mem->end); 321 idec->io.data = mem->buf + mem->start; 322 idec->io.data_size = MemDataSize(mem); 323 } 324 325 // Headers 326 static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { 327 MemBuffer* const mem = &idec->mem; 328 const uint8_t* data = mem->buf + mem->start; 329 size_t curr_size = MemDataSize(mem); 330 VP8StatusCode status; 331 WebPHeaderStructure headers; 332 333 headers.data = data; 334 headers.data_size = curr_size; 335 headers.have_all_data = 0; 336 status = WebPParseHeaders(&headers); 337 if (status == VP8_STATUS_NOT_ENOUGH_DATA) { 338 return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. 339 } else if (status != VP8_STATUS_OK) { 340 return IDecError(idec, status); 341 } 342 343 idec->chunk_size = headers.compressed_size; 344 idec->is_lossless = headers.is_lossless; 345 if (!idec->is_lossless) { 346 VP8Decoder* const dec = VP8New(); 347 if (dec == NULL) { 348 return VP8_STATUS_OUT_OF_MEMORY; 349 } 350 dec->incremental = 1; 351 idec->dec = dec; 352 dec->alpha_data = headers.alpha_data; 353 dec->alpha_data_size = headers.alpha_data_size; 354 ChangeState(idec, STATE_VP8_HEADER, headers.offset); 355 } else { 356 VP8LDecoder* const dec = VP8LNew(); 357 if (dec == NULL) { 358 return VP8_STATUS_OUT_OF_MEMORY; 359 } 360 idec->dec = dec; 361 ChangeState(idec, STATE_VP8L_HEADER, headers.offset); 362 } 363 return VP8_STATUS_OK; 364 } 365 366 static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { 367 const uint8_t* data = idec->mem.buf + idec->mem.start; 368 const size_t curr_size = MemDataSize(&idec->mem); 369 int width, height; 370 uint32_t bits; 371 372 if (curr_size < VP8_FRAME_HEADER_SIZE) { 373 // Not enough data bytes to extract VP8 Frame Header. 374 return VP8_STATUS_SUSPENDED; 375 } 376 if (!VP8GetInfo(data, curr_size, idec->chunk_size, &width, &height)) { 377 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 378 } 379 380 bits = data[0] | (data[1] << 8) | (data[2] << 16); 381 idec->mem.part0_size = (bits >> 5) + VP8_FRAME_HEADER_SIZE; 382 383 idec->io.data = data; 384 idec->io.data_size = curr_size; 385 idec->state = STATE_VP8_PARTS0; 386 return VP8_STATUS_OK; 387 } 388 389 // Partition #0 390 static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) { 391 VP8Decoder* const dec = (VP8Decoder*)idec->dec; 392 VP8BitReader* const br = &dec->br; 393 const size_t part_size = br->buf_end - br->buf; 394 MemBuffer* const mem = &idec->mem; 395 assert(!idec->is_lossless); 396 assert(mem->part0_buf == NULL); 397 // the following is a format limitation, no need for runtime check: 398 assert(part_size <= mem->part0_size); 399 if (part_size == 0) { // can't have zero-size partition #0 400 return VP8_STATUS_BITSTREAM_ERROR; 401 } 402 if (mem->mode == MEM_MODE_APPEND) { 403 // We copy and grab ownership of the partition #0 data. 404 uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); 405 if (part0_buf == NULL) { 406 return VP8_STATUS_OUT_OF_MEMORY; 407 } 408 memcpy(part0_buf, br->buf, part_size); 409 mem->part0_buf = part0_buf; 410 VP8BitReaderSetBuffer(br, part0_buf, part_size); 411 } else { 412 // Else: just keep pointers to the partition #0's data in dec->br. 413 } 414 mem->start += part_size; 415 return VP8_STATUS_OK; 416 } 417 418 static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { 419 VP8Decoder* const dec = (VP8Decoder*)idec->dec; 420 VP8Io* const io = &idec->io; 421 const WebPDecParams* const params = &idec->params; 422 WebPDecBuffer* const output = params->output; 423 424 // Wait till we have enough data for the whole partition #0 425 if (MemDataSize(&idec->mem) < idec->mem.part0_size) { 426 return VP8_STATUS_SUSPENDED; 427 } 428 429 if (!VP8GetHeaders(dec, io)) { 430 const VP8StatusCode status = dec->status; 431 if (status == VP8_STATUS_SUSPENDED || 432 status == VP8_STATUS_NOT_ENOUGH_DATA) { 433 // treating NOT_ENOUGH_DATA as SUSPENDED state 434 return VP8_STATUS_SUSPENDED; 435 } 436 return IDecError(idec, status); 437 } 438 439 // Allocate/Verify output buffer now 440 dec->status = WebPAllocateDecBuffer(io->width, io->height, params->options, 441 output); 442 if (dec->status != VP8_STATUS_OK) { 443 return IDecError(idec, dec->status); 444 } 445 // This change must be done before calling VP8InitFrame() 446 dec->mt_method = VP8GetThreadMethod(params->options, NULL, 447 io->width, io->height); 448 VP8InitDithering(params->options, dec); 449 450 dec->status = CopyParts0Data(idec); 451 if (dec->status != VP8_STATUS_OK) { 452 return IDecError(idec, dec->status); 453 } 454 455 // Finish setting up the decoding parameters. Will call io->setup(). 456 if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { 457 return IDecError(idec, dec->status); 458 } 459 460 // Note: past this point, teardown() must always be called 461 // in case of error. 462 idec->state = STATE_VP8_DATA; 463 // Allocate memory and prepare everything. 464 if (!VP8InitFrame(dec, io)) { 465 return IDecError(idec, dec->status); 466 } 467 return VP8_STATUS_OK; 468 } 469 470 // Remaining partitions 471 static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { 472 VP8Decoder* const dec = (VP8Decoder*)idec->dec; 473 VP8Io* const io = &idec->io; 474 475 // Make sure partition #0 has been read before, to set dec to ready. 476 if (!dec->ready) { 477 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 478 } 479 for (; dec->mb_y < dec->mb_h; ++dec->mb_y) { 480 if (idec->last_mb_y != dec->mb_y) { 481 if (!VP8ParseIntraModeRow(&dec->br, dec)) { 482 // note: normally, error shouldn't occur since we already have the whole 483 // partition0 available here in DecodeRemaining(). Reaching EOF while 484 // reading intra modes really means a BITSTREAM_ERROR. 485 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 486 } 487 idec->last_mb_y = dec->mb_y; 488 } 489 for (; dec->mb_x < dec->mb_w; ++dec->mb_x) { 490 VP8BitReader* const token_br = 491 &dec->parts[dec->mb_y & dec->num_parts_minus_one]; 492 MBContext context; 493 SaveContext(dec, token_br, &context); 494 if (!VP8DecodeMB(dec, token_br)) { 495 // We shouldn't fail when MAX_MB data was available 496 if (dec->num_parts_minus_one == 0 && 497 MemDataSize(&idec->mem) > MAX_MB_SIZE) { 498 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 499 } 500 // Synchronize the threads. 501 if (dec->mt_method > 0) { 502 if (!WebPGetWorkerInterface()->Sync(&dec->worker)) { 503 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 504 } 505 } 506 RestoreContext(&context, dec, token_br); 507 return VP8_STATUS_SUSPENDED; 508 } 509 // Release buffer only if there is only one partition 510 if (dec->num_parts_minus_one == 0) { 511 idec->mem.start = token_br->buf - idec->mem.buf; 512 assert(idec->mem.start <= idec->mem.end); 513 } 514 } 515 VP8InitScanline(dec); // Prepare for next scanline 516 517 // Reconstruct, filter and emit the row. 518 if (!VP8ProcessRow(dec, io)) { 519 return IDecError(idec, VP8_STATUS_USER_ABORT); 520 } 521 } 522 // Synchronize the thread and check for errors. 523 if (!VP8ExitCritical(dec, io)) { 524 idec->state = STATE_ERROR; // prevent re-entry in IDecError 525 return IDecError(idec, VP8_STATUS_USER_ABORT); 526 } 527 dec->ready = 0; 528 return FinishDecoding(idec); 529 } 530 531 static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec, 532 VP8StatusCode status) { 533 if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { 534 return VP8_STATUS_SUSPENDED; 535 } 536 return IDecError(idec, status); 537 } 538 539 static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { 540 VP8Io* const io = &idec->io; 541 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec; 542 const WebPDecParams* const params = &idec->params; 543 WebPDecBuffer* const output = params->output; 544 size_t curr_size = MemDataSize(&idec->mem); 545 assert(idec->is_lossless); 546 547 // Wait until there's enough data for decoding header. 548 if (curr_size < (idec->chunk_size >> 3)) { 549 dec->status = VP8_STATUS_SUSPENDED; 550 return ErrorStatusLossless(idec, dec->status); 551 } 552 553 if (!VP8LDecodeHeader(dec, io)) { 554 if (dec->status == VP8_STATUS_BITSTREAM_ERROR && 555 curr_size < idec->chunk_size) { 556 dec->status = VP8_STATUS_SUSPENDED; 557 } 558 return ErrorStatusLossless(idec, dec->status); 559 } 560 // Allocate/verify output buffer now. 561 dec->status = WebPAllocateDecBuffer(io->width, io->height, params->options, 562 output); 563 if (dec->status != VP8_STATUS_OK) { 564 return IDecError(idec, dec->status); 565 } 566 567 idec->state = STATE_VP8L_DATA; 568 return VP8_STATUS_OK; 569 } 570 571 static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { 572 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec; 573 const size_t curr_size = MemDataSize(&idec->mem); 574 assert(idec->is_lossless); 575 576 // Switch to incremental decoding if we don't have all the bytes available. 577 dec->incremental = (curr_size < idec->chunk_size); 578 579 if (!VP8LDecodeImage(dec)) { 580 return ErrorStatusLossless(idec, dec->status); 581 } 582 assert(dec->status == VP8_STATUS_OK || dec->status == VP8_STATUS_SUSPENDED); 583 return (dec->status == VP8_STATUS_SUSPENDED) ? dec->status 584 : FinishDecoding(idec); 585 } 586 587 // Main decoding loop 588 static VP8StatusCode IDecode(WebPIDecoder* idec) { 589 VP8StatusCode status = VP8_STATUS_SUSPENDED; 590 591 if (idec->state == STATE_WEBP_HEADER) { 592 status = DecodeWebPHeaders(idec); 593 } else { 594 if (idec->dec == NULL) { 595 return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. 596 } 597 } 598 if (idec->state == STATE_VP8_HEADER) { 599 status = DecodeVP8FrameHeader(idec); 600 } 601 if (idec->state == STATE_VP8_PARTS0) { 602 status = DecodePartition0(idec); 603 } 604 if (idec->state == STATE_VP8_DATA) { 605 const VP8Decoder* const dec = (VP8Decoder*)idec->dec; 606 if (dec == NULL) { 607 return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. 608 } 609 status = DecodeRemaining(idec); 610 } 611 if (idec->state == STATE_VP8L_HEADER) { 612 status = DecodeVP8LHeader(idec); 613 } 614 if (idec->state == STATE_VP8L_DATA) { 615 status = DecodeVP8LData(idec); 616 } 617 return status; 618 } 619 620 //------------------------------------------------------------------------------ 621 // Internal constructor 622 623 WEBP_NODISCARD static WebPIDecoder* NewDecoder( 624 WebPDecBuffer* const output_buffer, 625 const WebPBitstreamFeatures* const features) { 626 WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); 627 if (idec == NULL) { 628 return NULL; 629 } 630 631 idec->state = STATE_WEBP_HEADER; 632 idec->chunk_size = 0; 633 634 idec->last_mb_y = -1; 635 636 InitMemBuffer(&idec->mem); 637 if (!WebPInitDecBuffer(&idec->output) || !VP8InitIo(&idec->io)) { 638 WebPSafeFree(idec); 639 return NULL; 640 } 641 642 WebPResetDecParams(&idec->params); 643 if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) { 644 idec->params.output = &idec->output; 645 idec->final_output = output_buffer; 646 if (output_buffer != NULL) { 647 idec->params.output->colorspace = output_buffer->colorspace; 648 } 649 } else { 650 idec->params.output = output_buffer; 651 idec->final_output = NULL; 652 } 653 WebPInitCustomIo(&idec->params, &idec->io); // Plug the I/O functions. 654 655 return idec; 656 } 657 658 //------------------------------------------------------------------------------ 659 // Public functions 660 661 WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { 662 return NewDecoder(output_buffer, NULL); 663 } 664 665 WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, 666 WebPDecoderConfig* config) { 667 WebPIDecoder* idec; 668 WebPBitstreamFeatures tmp_features; 669 WebPBitstreamFeatures* const features = 670 (config == NULL) ? &tmp_features : &config->input; 671 memset(&tmp_features, 0, sizeof(tmp_features)); 672 673 // Parse the bitstream's features, if requested: 674 if (data != NULL && data_size > 0) { 675 if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) { 676 return NULL; 677 } 678 } 679 680 // Create an instance of the incremental decoder 681 idec = (config != NULL) ? NewDecoder(&config->output, features) 682 : NewDecoder(NULL, features); 683 if (idec == NULL) { 684 return NULL; 685 } 686 // Finish initialization 687 if (config != NULL) { 688 idec->params.options = &config->options; 689 } 690 return idec; 691 } 692 693 void WebPIDelete(WebPIDecoder* idec) { 694 if (idec == NULL) return; 695 if (idec->dec != NULL) { 696 if (!idec->is_lossless) { 697 if (idec->state == STATE_VP8_DATA) { 698 // Synchronize the thread, clean-up and check for errors. 699 // TODO(vrabaud) do we care about the return result? 700 (void)VP8ExitCritical((VP8Decoder*)idec->dec, &idec->io); 701 } 702 VP8Delete((VP8Decoder*)idec->dec); 703 } else { 704 VP8LDelete((VP8LDecoder*)idec->dec); 705 } 706 } 707 ClearMemBuffer(&idec->mem); 708 WebPFreeDecBuffer(&idec->output); 709 WebPSafeFree(idec); 710 } 711 712 //------------------------------------------------------------------------------ 713 // Wrapper toward WebPINewDecoder 714 715 WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer, 716 size_t output_buffer_size, int output_stride) { 717 const int is_external_memory = (output_buffer != NULL) ? 1 : 0; 718 WebPIDecoder* idec; 719 720 if (csp >= MODE_YUV) return NULL; 721 if (is_external_memory == 0) { // Overwrite parameters to sane values. 722 output_buffer_size = 0; 723 output_stride = 0; 724 } else { // A buffer was passed. Validate the other params. 725 if (output_stride == 0 || output_buffer_size == 0) { 726 return NULL; // invalid parameter. 727 } 728 } 729 idec = WebPINewDecoder(NULL); 730 if (idec == NULL) return NULL; 731 idec->output.colorspace = csp; 732 idec->output.is_external_memory = is_external_memory; 733 idec->output.u.RGBA.rgba = output_buffer; 734 idec->output.u.RGBA.stride = output_stride; 735 idec->output.u.RGBA.size = output_buffer_size; 736 return idec; 737 } 738 739 WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, 740 uint8_t* u, size_t u_size, int u_stride, 741 uint8_t* v, size_t v_size, int v_stride, 742 uint8_t* a, size_t a_size, int a_stride) { 743 const int is_external_memory = (luma != NULL) ? 1 : 0; 744 WebPIDecoder* idec; 745 WEBP_CSP_MODE colorspace; 746 747 if (is_external_memory == 0) { // Overwrite parameters to sane values. 748 luma_size = u_size = v_size = a_size = 0; 749 luma_stride = u_stride = v_stride = a_stride = 0; 750 u = v = a = NULL; 751 colorspace = MODE_YUVA; 752 } else { // A luma buffer was passed. Validate the other parameters. 753 if (u == NULL || v == NULL) return NULL; 754 if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; 755 if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; 756 if (a != NULL) { 757 if (a_size == 0 || a_stride == 0) return NULL; 758 } 759 colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; 760 } 761 762 idec = WebPINewDecoder(NULL); 763 if (idec == NULL) return NULL; 764 765 idec->output.colorspace = colorspace; 766 idec->output.is_external_memory = is_external_memory; 767 idec->output.u.YUVA.y = luma; 768 idec->output.u.YUVA.y_stride = luma_stride; 769 idec->output.u.YUVA.y_size = luma_size; 770 idec->output.u.YUVA.u = u; 771 idec->output.u.YUVA.u_stride = u_stride; 772 idec->output.u.YUVA.u_size = u_size; 773 idec->output.u.YUVA.v = v; 774 idec->output.u.YUVA.v_stride = v_stride; 775 idec->output.u.YUVA.v_size = v_size; 776 idec->output.u.YUVA.a = a; 777 idec->output.u.YUVA.a_stride = a_stride; 778 idec->output.u.YUVA.a_size = a_size; 779 return idec; 780 } 781 782 WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, 783 uint8_t* u, size_t u_size, int u_stride, 784 uint8_t* v, size_t v_size, int v_stride) { 785 return WebPINewYUVA(luma, luma_size, luma_stride, 786 u, u_size, u_stride, 787 v, v_size, v_stride, 788 NULL, 0, 0); 789 } 790 791 //------------------------------------------------------------------------------ 792 793 static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { 794 assert(idec); 795 if (idec->state == STATE_ERROR) { 796 return VP8_STATUS_BITSTREAM_ERROR; 797 } 798 if (idec->state == STATE_DONE) { 799 return VP8_STATUS_OK; 800 } 801 return VP8_STATUS_SUSPENDED; 802 } 803 804 VP8StatusCode WebPIAppend(WebPIDecoder* idec, 805 const uint8_t* data, size_t data_size) { 806 VP8StatusCode status; 807 if (idec == NULL || data == NULL) { 808 return VP8_STATUS_INVALID_PARAM; 809 } 810 status = IDecCheckStatus(idec); 811 if (status != VP8_STATUS_SUSPENDED) { 812 return status; 813 } 814 // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. 815 if (!CheckMemBufferMode(&idec->mem, MEM_MODE_APPEND)) { 816 return VP8_STATUS_INVALID_PARAM; 817 } 818 // Append data to memory buffer 819 if (!AppendToMemBuffer(idec, data, data_size)) { 820 return VP8_STATUS_OUT_OF_MEMORY; 821 } 822 return IDecode(idec); 823 } 824 825 VP8StatusCode WebPIUpdate(WebPIDecoder* idec, 826 const uint8_t* data, size_t data_size) { 827 VP8StatusCode status; 828 if (idec == NULL || data == NULL) { 829 return VP8_STATUS_INVALID_PARAM; 830 } 831 status = IDecCheckStatus(idec); 832 if (status != VP8_STATUS_SUSPENDED) { 833 return status; 834 } 835 // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. 836 if (!CheckMemBufferMode(&idec->mem, MEM_MODE_MAP)) { 837 return VP8_STATUS_INVALID_PARAM; 838 } 839 // Make the memory buffer point to the new buffer 840 if (!RemapMemBuffer(idec, data, data_size)) { 841 return VP8_STATUS_INVALID_PARAM; 842 } 843 return IDecode(idec); 844 } 845 846 //------------------------------------------------------------------------------ 847 848 static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { 849 if (idec == NULL || idec->dec == NULL) { 850 return NULL; 851 } 852 if (idec->state <= STATE_VP8_PARTS0) { 853 return NULL; 854 } 855 if (idec->final_output != NULL) { 856 return NULL; // not yet slow-copied 857 } 858 return idec->params.output; 859 } 860 861 const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, 862 int* left, int* top, 863 int* width, int* height) { 864 const WebPDecBuffer* const src = GetOutputBuffer(idec); 865 if (left != NULL) *left = 0; 866 if (top != NULL) *top = 0; 867 if (src != NULL) { 868 if (width != NULL) *width = src->width; 869 if (height != NULL) *height = idec->params.last_y; 870 } else { 871 if (width != NULL) *width = 0; 872 if (height != NULL) *height = 0; 873 } 874 return src; 875 } 876 877 WEBP_NODISCARD uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, 878 int* width, int* height, int* stride) { 879 const WebPDecBuffer* const src = GetOutputBuffer(idec); 880 if (src == NULL) return NULL; 881 if (src->colorspace >= MODE_YUV) { 882 return NULL; 883 } 884 885 if (last_y != NULL) *last_y = idec->params.last_y; 886 if (width != NULL) *width = src->width; 887 if (height != NULL) *height = src->height; 888 if (stride != NULL) *stride = src->u.RGBA.stride; 889 890 return src->u.RGBA.rgba; 891 } 892 893 WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, 894 uint8_t** u, uint8_t** v, uint8_t** a, 895 int* width, int* height, int* stride, 896 int* uv_stride, int* a_stride) { 897 const WebPDecBuffer* const src = GetOutputBuffer(idec); 898 if (src == NULL) return NULL; 899 if (src->colorspace < MODE_YUV) { 900 return NULL; 901 } 902 903 if (last_y != NULL) *last_y = idec->params.last_y; 904 if (u != NULL) *u = src->u.YUVA.u; 905 if (v != NULL) *v = src->u.YUVA.v; 906 if (a != NULL) *a = src->u.YUVA.a; 907 if (width != NULL) *width = src->width; 908 if (height != NULL) *height = src->height; 909 if (stride != NULL) *stride = src->u.YUVA.y_stride; 910 if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; 911 if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; 912 913 return src->u.YUVA.y; 914 } 915 916 int WebPISetIOHooks(WebPIDecoder* const idec, 917 VP8IoPutHook put, 918 VP8IoSetupHook setup, 919 VP8IoTeardownHook teardown, 920 void* user_data) { 921 if (idec == NULL || idec->state > STATE_WEBP_HEADER) { 922 return 0; 923 } 924 925 idec->io.put = put; 926 idec->io.setup = setup; 927 idec->io.teardown = teardown; 928 idec->io.opaque = user_data; 929 930 return 1; 931 }