1 /* 2 * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "libyuv/mjpeg_decoder.h" 12 13 #ifdef HAVE_JPEG 14 #include <assert.h> 15 16 #if !defined(__pnacl__) && !defined(__CLR_VER) && \ 17 !defined(COVERAGE_ENABLED) && !defined(TARGET_IPHONE_SIMULATOR) 18 // Must be included before jpeglib. 19 #include <setjmp.h> 20 #define HAVE_SETJMP 21 22 #if defined(_MSC_VER) 23 // disable warning 4324: structure was padded due to __declspec(align()) 24 #pragma warning(disable : 4324) 25 #endif 26 27 #endif 28 struct FILE; // For jpeglib.h. 29 30 // C++ build requires extern C for jpeg internals. 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 #include <jpeglib.h> 36 37 #ifdef __cplusplus 38 } // extern "C" 39 #endif 40 41 #include "libyuv/planar_functions.h" // For CopyPlane(). 42 43 namespace libyuv { 44 45 #ifdef HAVE_SETJMP 46 struct SetJmpErrorMgr { 47 jpeg_error_mgr base; // Must be at the top 48 jmp_buf setjmp_buffer; 49 }; 50 #endif 51 52 const int MJpegDecoder::kColorSpaceUnknown = JCS_UNKNOWN; 53 const int MJpegDecoder::kColorSpaceGrayscale = JCS_GRAYSCALE; 54 const int MJpegDecoder::kColorSpaceRgb = JCS_RGB; 55 const int MJpegDecoder::kColorSpaceYCbCr = JCS_YCbCr; 56 const int MJpegDecoder::kColorSpaceCMYK = JCS_CMYK; 57 const int MJpegDecoder::kColorSpaceYCCK = JCS_YCCK; 58 59 // Methods that are passed to jpeglib. 60 boolean fill_input_buffer(jpeg_decompress_struct* cinfo); 61 void init_source(jpeg_decompress_struct* cinfo); 62 void skip_input_data(jpeg_decompress_struct* cinfo, long num_bytes); // NOLINT 63 void term_source(jpeg_decompress_struct* cinfo); 64 void ErrorHandler(jpeg_common_struct* cinfo); 65 void OutputHandler(jpeg_common_struct* cinfo); 66 67 MJpegDecoder::MJpegDecoder() 68 : has_scanline_padding_(LIBYUV_FALSE), 69 num_outbufs_(0), 70 scanlines_(NULL), 71 scanlines_sizes_(NULL), 72 databuf_(NULL), 73 databuf_strides_(NULL) { 74 decompress_struct_ = new jpeg_decompress_struct; 75 source_mgr_ = new jpeg_source_mgr; 76 #ifdef HAVE_SETJMP 77 error_mgr_ = new SetJmpErrorMgr; 78 decompress_struct_->err = jpeg_std_error(&error_mgr_->base); 79 // Override standard exit()-based error handler. 80 error_mgr_->base.error_exit = &ErrorHandler; 81 error_mgr_->base.output_message = &OutputHandler; 82 #endif 83 decompress_struct_->client_data = NULL; 84 source_mgr_->init_source = &init_source; 85 source_mgr_->fill_input_buffer = &fill_input_buffer; 86 source_mgr_->skip_input_data = &skip_input_data; 87 source_mgr_->resync_to_restart = &jpeg_resync_to_restart; 88 source_mgr_->term_source = &term_source; 89 jpeg_create_decompress(decompress_struct_); 90 decompress_struct_->src = source_mgr_; 91 buf_vec_.buffers = &buf_; 92 buf_vec_.len = 1; 93 } 94 95 MJpegDecoder::~MJpegDecoder() { 96 jpeg_destroy_decompress(decompress_struct_); 97 delete decompress_struct_; 98 delete source_mgr_; 99 #ifdef HAVE_SETJMP 100 delete error_mgr_; 101 #endif 102 DestroyOutputBuffers(); 103 } 104 105 LIBYUV_BOOL MJpegDecoder::LoadFrame(const uint8* src, size_t src_len) { 106 if (!ValidateJpeg(src, src_len)) { 107 return LIBYUV_FALSE; 108 } 109 110 buf_.data = src; 111 buf_.len = static_cast<int>(src_len); 112 buf_vec_.pos = 0; 113 decompress_struct_->client_data = &buf_vec_; 114 #ifdef HAVE_SETJMP 115 if (setjmp(error_mgr_->setjmp_buffer)) { 116 // We called jpeg_read_header, it experienced an error, and we called 117 // longjmp() and rewound the stack to here. Return error. 118 return LIBYUV_FALSE; 119 } 120 #endif 121 if (jpeg_read_header(decompress_struct_, TRUE) != JPEG_HEADER_OK) { 122 // ERROR: Bad MJPEG header 123 return LIBYUV_FALSE; 124 } 125 AllocOutputBuffers(GetNumComponents()); 126 for (int i = 0; i < num_outbufs_; ++i) { 127 int scanlines_size = GetComponentScanlinesPerImcuRow(i); 128 if (scanlines_sizes_[i] != scanlines_size) { 129 if (scanlines_[i]) { 130 delete scanlines_[i]; 131 } 132 scanlines_[i] = new uint8*[scanlines_size]; 133 scanlines_sizes_[i] = scanlines_size; 134 } 135 136 // We allocate padding for the final scanline to pad it up to DCTSIZE bytes 137 // to avoid memory errors, since jpeglib only reads full MCUs blocks. For 138 // the preceding scanlines, the padding is not needed/wanted because the 139 // following addresses will already be valid (they are the initial bytes of 140 // the next scanline) and will be overwritten when jpeglib writes out that 141 // next scanline. 142 int databuf_stride = GetComponentStride(i); 143 int databuf_size = scanlines_size * databuf_stride; 144 if (databuf_strides_[i] != databuf_stride) { 145 if (databuf_[i]) { 146 delete databuf_[i]; 147 } 148 databuf_[i] = new uint8[databuf_size]; 149 databuf_strides_[i] = databuf_stride; 150 } 151 152 if (GetComponentStride(i) != GetComponentWidth(i)) { 153 has_scanline_padding_ = LIBYUV_TRUE; 154 } 155 } 156 return LIBYUV_TRUE; 157 } 158 159 static int DivideAndRoundUp(int numerator, int denominator) { 160 return (numerator + denominator - 1) / denominator; 161 } 162 163 static int DivideAndRoundDown(int numerator, int denominator) { 164 return numerator / denominator; 165 } 166 167 // Returns width of the last loaded frame. 168 int MJpegDecoder::GetWidth() { 169 return decompress_struct_->image_width; 170 } 171 172 // Returns height of the last loaded frame. 173 int MJpegDecoder::GetHeight() { 174 return decompress_struct_->image_height; 175 } 176 177 // Returns format of the last loaded frame. The return value is one of the 178 // kColorSpace* constants. 179 int MJpegDecoder::GetColorSpace() { 180 return decompress_struct_->jpeg_color_space; 181 } 182 183 // Number of color components in the color space. 184 int MJpegDecoder::GetNumComponents() { 185 return decompress_struct_->num_components; 186 } 187 188 // Sample factors of the n-th component. 189 int MJpegDecoder::GetHorizSampFactor(int component) { 190 return decompress_struct_->comp_info[component].h_samp_factor; 191 } 192 193 int MJpegDecoder::GetVertSampFactor(int component) { 194 return decompress_struct_->comp_info[component].v_samp_factor; 195 } 196 197 int MJpegDecoder::GetHorizSubSampFactor(int component) { 198 return decompress_struct_->max_h_samp_factor / GetHorizSampFactor(component); 199 } 200 201 int MJpegDecoder::GetVertSubSampFactor(int component) { 202 return decompress_struct_->max_v_samp_factor / GetVertSampFactor(component); 203 } 204 205 int MJpegDecoder::GetImageScanlinesPerImcuRow() { 206 return decompress_struct_->max_v_samp_factor * DCTSIZE; 207 } 208 209 int MJpegDecoder::GetComponentScanlinesPerImcuRow(int component) { 210 int vs = GetVertSubSampFactor(component); 211 return DivideAndRoundUp(GetImageScanlinesPerImcuRow(), vs); 212 } 213 214 int MJpegDecoder::GetComponentWidth(int component) { 215 int hs = GetHorizSubSampFactor(component); 216 return DivideAndRoundUp(GetWidth(), hs); 217 } 218 219 int MJpegDecoder::GetComponentHeight(int component) { 220 int vs = GetVertSubSampFactor(component); 221 return DivideAndRoundUp(GetHeight(), vs); 222 } 223 224 // Get width in bytes padded out to a multiple of DCTSIZE 225 int MJpegDecoder::GetComponentStride(int component) { 226 return (GetComponentWidth(component) + DCTSIZE - 1) & ~(DCTSIZE - 1); 227 } 228 229 int MJpegDecoder::GetComponentSize(int component) { 230 return GetComponentWidth(component) * GetComponentHeight(component); 231 } 232 233 LIBYUV_BOOL MJpegDecoder::UnloadFrame() { 234 #ifdef HAVE_SETJMP 235 if (setjmp(error_mgr_->setjmp_buffer)) { 236 // We called jpeg_abort_decompress, it experienced an error, and we called 237 // longjmp() and rewound the stack to here. Return error. 238 return LIBYUV_FALSE; 239 } 240 #endif 241 jpeg_abort_decompress(decompress_struct_); 242 return LIBYUV_TRUE; 243 } 244 245 // TODO(fbarchard): Allow rectangle to be specified: x, y, width, height. 246 LIBYUV_BOOL MJpegDecoder::DecodeToBuffers(uint8** planes, 247 int dst_width, 248 int dst_height) { 249 if (dst_width != GetWidth() || dst_height > GetHeight()) { 250 // ERROR: Bad dimensions 251 return LIBYUV_FALSE; 252 } 253 #ifdef HAVE_SETJMP 254 if (setjmp(error_mgr_->setjmp_buffer)) { 255 // We called into jpeglib, it experienced an error sometime during this 256 // function call, and we called longjmp() and rewound the stack to here. 257 // Return error. 258 return LIBYUV_FALSE; 259 } 260 #endif 261 if (!StartDecode()) { 262 return LIBYUV_FALSE; 263 } 264 SetScanlinePointers(databuf_); 265 int lines_left = dst_height; 266 // Compute amount of lines to skip to implement vertical crop. 267 // TODO(fbarchard): Ensure skip is a multiple of maximum component 268 // subsample. ie 2 269 int skip = (GetHeight() - dst_height) / 2; 270 if (skip > 0) { 271 // There is no API to skip lines in the output data, so we read them 272 // into the temp buffer. 273 while (skip >= GetImageScanlinesPerImcuRow()) { 274 if (!DecodeImcuRow()) { 275 FinishDecode(); 276 return LIBYUV_FALSE; 277 } 278 skip -= GetImageScanlinesPerImcuRow(); 279 } 280 if (skip > 0) { 281 // Have a partial iMCU row left over to skip. Must read it and then 282 // copy the parts we want into the destination. 283 if (!DecodeImcuRow()) { 284 FinishDecode(); 285 return LIBYUV_FALSE; 286 } 287 for (int i = 0; i < num_outbufs_; ++i) { 288 // TODO(fbarchard): Compute skip to avoid this 289 assert(skip % GetVertSubSampFactor(i) == 0); 290 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i)); 291 int scanlines_to_copy = 292 GetComponentScanlinesPerImcuRow(i) - rows_to_skip; 293 int data_to_skip = rows_to_skip * GetComponentStride(i); 294 CopyPlane(databuf_[i] + data_to_skip, GetComponentStride(i), planes[i], 295 GetComponentWidth(i), GetComponentWidth(i), 296 scanlines_to_copy); 297 planes[i] += scanlines_to_copy * GetComponentWidth(i); 298 } 299 lines_left -= (GetImageScanlinesPerImcuRow() - skip); 300 } 301 } 302 303 // Read full MCUs but cropped horizontally 304 for (; lines_left > GetImageScanlinesPerImcuRow(); 305 lines_left -= GetImageScanlinesPerImcuRow()) { 306 if (!DecodeImcuRow()) { 307 FinishDecode(); 308 return LIBYUV_FALSE; 309 } 310 for (int i = 0; i < num_outbufs_; ++i) { 311 int scanlines_to_copy = GetComponentScanlinesPerImcuRow(i); 312 CopyPlane(databuf_[i], GetComponentStride(i), planes[i], 313 GetComponentWidth(i), GetComponentWidth(i), scanlines_to_copy); 314 planes[i] += scanlines_to_copy * GetComponentWidth(i); 315 } 316 } 317 318 if (lines_left > 0) { 319 // Have a partial iMCU row left over to decode. 320 if (!DecodeImcuRow()) { 321 FinishDecode(); 322 return LIBYUV_FALSE; 323 } 324 for (int i = 0; i < num_outbufs_; ++i) { 325 int scanlines_to_copy = 326 DivideAndRoundUp(lines_left, GetVertSubSampFactor(i)); 327 CopyPlane(databuf_[i], GetComponentStride(i), planes[i], 328 GetComponentWidth(i), GetComponentWidth(i), scanlines_to_copy); 329 planes[i] += scanlines_to_copy * GetComponentWidth(i); 330 } 331 } 332 return FinishDecode(); 333 } 334 335 LIBYUV_BOOL MJpegDecoder::DecodeToCallback(CallbackFunction fn, 336 void* opaque, 337 int dst_width, 338 int dst_height) { 339 if (dst_width != GetWidth() || dst_height > GetHeight()) { 340 // ERROR: Bad dimensions 341 return LIBYUV_FALSE; 342 } 343 #ifdef HAVE_SETJMP 344 if (setjmp(error_mgr_->setjmp_buffer)) { 345 // We called into jpeglib, it experienced an error sometime during this 346 // function call, and we called longjmp() and rewound the stack to here. 347 // Return error. 348 return LIBYUV_FALSE; 349 } 350 #endif 351 if (!StartDecode()) { 352 return LIBYUV_FALSE; 353 } 354 SetScanlinePointers(databuf_); 355 int lines_left = dst_height; 356 // TODO(fbarchard): Compute amount of lines to skip to implement vertical crop 357 int skip = (GetHeight() - dst_height) / 2; 358 if (skip > 0) { 359 while (skip >= GetImageScanlinesPerImcuRow()) { 360 if (!DecodeImcuRow()) { 361 FinishDecode(); 362 return LIBYUV_FALSE; 363 } 364 skip -= GetImageScanlinesPerImcuRow(); 365 } 366 if (skip > 0) { 367 // Have a partial iMCU row left over to skip. 368 if (!DecodeImcuRow()) { 369 FinishDecode(); 370 return LIBYUV_FALSE; 371 } 372 for (int i = 0; i < num_outbufs_; ++i) { 373 // TODO(fbarchard): Compute skip to avoid this 374 assert(skip % GetVertSubSampFactor(i) == 0); 375 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i)); 376 int data_to_skip = rows_to_skip * GetComponentStride(i); 377 // Change our own data buffer pointers so we can pass them to the 378 // callback. 379 databuf_[i] += data_to_skip; 380 } 381 int scanlines_to_copy = GetImageScanlinesPerImcuRow() - skip; 382 (*fn)(opaque, databuf_, databuf_strides_, scanlines_to_copy); 383 // Now change them back. 384 for (int i = 0; i < num_outbufs_; ++i) { 385 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i)); 386 int data_to_skip = rows_to_skip * GetComponentStride(i); 387 databuf_[i] -= data_to_skip; 388 } 389 lines_left -= scanlines_to_copy; 390 } 391 } 392 // Read full MCUs until we get to the crop point. 393 for (; lines_left >= GetImageScanlinesPerImcuRow(); 394 lines_left -= GetImageScanlinesPerImcuRow()) { 395 if (!DecodeImcuRow()) { 396 FinishDecode(); 397 return LIBYUV_FALSE; 398 } 399 (*fn)(opaque, databuf_, databuf_strides_, GetImageScanlinesPerImcuRow()); 400 } 401 if (lines_left > 0) { 402 // Have a partial iMCU row left over to decode. 403 if (!DecodeImcuRow()) { 404 FinishDecode(); 405 return LIBYUV_FALSE; 406 } 407 (*fn)(opaque, databuf_, databuf_strides_, lines_left); 408 } 409 return FinishDecode(); 410 } 411 412 void init_source(j_decompress_ptr cinfo) { 413 fill_input_buffer(cinfo); 414 } 415 416 boolean fill_input_buffer(j_decompress_ptr cinfo) { 417 BufferVector* buf_vec = reinterpret_cast<BufferVector*>(cinfo->client_data); 418 if (buf_vec->pos >= buf_vec->len) { 419 assert(0 && "No more data"); 420 // ERROR: No more data 421 return FALSE; 422 } 423 cinfo->src->next_input_byte = buf_vec->buffers[buf_vec->pos].data; 424 cinfo->src->bytes_in_buffer = buf_vec->buffers[buf_vec->pos].len; 425 ++buf_vec->pos; 426 return TRUE; 427 } 428 429 void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { // NOLINT 430 cinfo->src->next_input_byte += num_bytes; 431 } 432 433 void term_source(j_decompress_ptr cinfo) { 434 (void)cinfo; // Nothing to do. 435 } 436 437 #ifdef HAVE_SETJMP 438 void ErrorHandler(j_common_ptr cinfo) { 439 // This is called when a jpeglib command experiences an error. Unfortunately 440 // jpeglib's error handling model is not very flexible, because it expects the 441 // error handler to not return--i.e., it wants the program to terminate. To 442 // recover from errors we use setjmp() as shown in their example. setjmp() is 443 // C's implementation for the "call with current continuation" functionality 444 // seen in some functional programming languages. 445 // A formatted message can be output, but is unsafe for release. 446 #ifdef DEBUG 447 char buf[JMSG_LENGTH_MAX]; 448 (*cinfo->err->format_message)(cinfo, buf); 449 // ERROR: Error in jpeglib: buf 450 #endif 451 452 SetJmpErrorMgr* mgr = reinterpret_cast<SetJmpErrorMgr*>(cinfo->err); 453 // This rewinds the call stack to the point of the corresponding setjmp() 454 // and causes it to return (for a second time) with value 1. 455 longjmp(mgr->setjmp_buffer, 1); 456 } 457 458 // Suppress fprintf warnings. 459 void OutputHandler(j_common_ptr cinfo) { 460 (void)cinfo; 461 } 462 463 #endif // HAVE_SETJMP 464 465 void MJpegDecoder::AllocOutputBuffers(int num_outbufs) { 466 if (num_outbufs != num_outbufs_) { 467 // We could perhaps optimize this case to resize the output buffers without 468 // necessarily having to delete and recreate each one, but it's not worth 469 // it. 470 DestroyOutputBuffers(); 471 472 scanlines_ = new uint8**[num_outbufs]; 473 scanlines_sizes_ = new int[num_outbufs]; 474 databuf_ = new uint8*[num_outbufs]; 475 databuf_strides_ = new int[num_outbufs]; 476 477 for (int i = 0; i < num_outbufs; ++i) { 478 scanlines_[i] = NULL; 479 scanlines_sizes_[i] = 0; 480 databuf_[i] = NULL; 481 databuf_strides_[i] = 0; 482 } 483 484 num_outbufs_ = num_outbufs; 485 } 486 } 487 488 void MJpegDecoder::DestroyOutputBuffers() { 489 for (int i = 0; i < num_outbufs_; ++i) { 490 delete[] scanlines_[i]; 491 delete[] databuf_[i]; 492 } 493 delete[] scanlines_; 494 delete[] databuf_; 495 delete[] scanlines_sizes_; 496 delete[] databuf_strides_; 497 scanlines_ = NULL; 498 databuf_ = NULL; 499 scanlines_sizes_ = NULL; 500 databuf_strides_ = NULL; 501 num_outbufs_ = 0; 502 } 503 504 // JDCT_IFAST and do_block_smoothing improve performance substantially. 505 LIBYUV_BOOL MJpegDecoder::StartDecode() { 506 decompress_struct_->raw_data_out = TRUE; 507 decompress_struct_->dct_method = JDCT_IFAST; // JDCT_ISLOW is default 508 decompress_struct_->dither_mode = JDITHER_NONE; 509 // Not applicable to 'raw': 510 decompress_struct_->do_fancy_upsampling = (boolean)(LIBYUV_FALSE); 511 // Only for buffered mode: 512 decompress_struct_->enable_2pass_quant = (boolean)(LIBYUV_FALSE); 513 // Blocky but fast: 514 decompress_struct_->do_block_smoothing = (boolean)(LIBYUV_FALSE); 515 516 if (!jpeg_start_decompress(decompress_struct_)) { 517 // ERROR: Couldn't start JPEG decompressor"; 518 return LIBYUV_FALSE; 519 } 520 return LIBYUV_TRUE; 521 } 522 523 LIBYUV_BOOL MJpegDecoder::FinishDecode() { 524 // jpeglib considers it an error if we finish without decoding the whole 525 // image, so we call "abort" rather than "finish". 526 jpeg_abort_decompress(decompress_struct_); 527 return LIBYUV_TRUE; 528 } 529 530 void MJpegDecoder::SetScanlinePointers(uint8** data) { 531 for (int i = 0; i < num_outbufs_; ++i) { 532 uint8* data_i = data[i]; 533 for (int j = 0; j < scanlines_sizes_[i]; ++j) { 534 scanlines_[i][j] = data_i; 535 data_i += GetComponentStride(i); 536 } 537 } 538 } 539 540 inline LIBYUV_BOOL MJpegDecoder::DecodeImcuRow() { 541 return (unsigned int)(GetImageScanlinesPerImcuRow()) == 542 jpeg_read_raw_data(decompress_struct_, scanlines_, 543 GetImageScanlinesPerImcuRow()); 544 } 545 546 // The helper function which recognizes the jpeg sub-sampling type. 547 JpegSubsamplingType MJpegDecoder::JpegSubsamplingTypeHelper( 548 int* subsample_x, 549 int* subsample_y, 550 int number_of_components) { 551 if (number_of_components == 3) { // Color images. 552 if (subsample_x[0] == 1 && subsample_y[0] == 1 && subsample_x[1] == 2 && 553 subsample_y[1] == 2 && subsample_x[2] == 2 && subsample_y[2] == 2) { 554 return kJpegYuv420; 555 } else if (subsample_x[0] == 1 && subsample_y[0] == 1 && 556 subsample_x[1] == 2 && subsample_y[1] == 1 && 557 subsample_x[2] == 2 && subsample_y[2] == 1) { 558 return kJpegYuv422; 559 } else if (subsample_x[0] == 1 && subsample_y[0] == 1 && 560 subsample_x[1] == 1 && subsample_y[1] == 1 && 561 subsample_x[2] == 1 && subsample_y[2] == 1) { 562 return kJpegYuv444; 563 } 564 } else if (number_of_components == 1) { // Grey-scale images. 565 if (subsample_x[0] == 1 && subsample_y[0] == 1) { 566 return kJpegYuv400; 567 } 568 } 569 return kJpegUnknown; 570 } 571 572 } // namespace libyuv 573 #endif // HAVE_JPEG 574