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 / 199 GetHorizSampFactor(component); 200 } 201 202 int MJpegDecoder::GetVertSubSampFactor(int component) { 203 return decompress_struct_->max_v_samp_factor / 204 GetVertSampFactor(component); 205 } 206 207 int MJpegDecoder::GetImageScanlinesPerImcuRow() { 208 return decompress_struct_->max_v_samp_factor * DCTSIZE; 209 } 210 211 int MJpegDecoder::GetComponentScanlinesPerImcuRow(int component) { 212 int vs = GetVertSubSampFactor(component); 213 return DivideAndRoundUp(GetImageScanlinesPerImcuRow(), vs); 214 } 215 216 int MJpegDecoder::GetComponentWidth(int component) { 217 int hs = GetHorizSubSampFactor(component); 218 return DivideAndRoundUp(GetWidth(), hs); 219 } 220 221 int MJpegDecoder::GetComponentHeight(int component) { 222 int vs = GetVertSubSampFactor(component); 223 return DivideAndRoundUp(GetHeight(), vs); 224 } 225 226 // Get width in bytes padded out to a multiple of DCTSIZE 227 int MJpegDecoder::GetComponentStride(int component) { 228 return (GetComponentWidth(component) + DCTSIZE - 1) & ~(DCTSIZE - 1); 229 } 230 231 int MJpegDecoder::GetComponentSize(int component) { 232 return GetComponentWidth(component) * GetComponentHeight(component); 233 } 234 235 LIBYUV_BOOL MJpegDecoder::UnloadFrame() { 236 #ifdef HAVE_SETJMP 237 if (setjmp(error_mgr_->setjmp_buffer)) { 238 // We called jpeg_abort_decompress, it experienced an error, and we called 239 // longjmp() and rewound the stack to here. Return error. 240 return LIBYUV_FALSE; 241 } 242 #endif 243 jpeg_abort_decompress(decompress_struct_); 244 return LIBYUV_TRUE; 245 } 246 247 // TODO(fbarchard): Allow rectangle to be specified: x, y, width, height. 248 LIBYUV_BOOL MJpegDecoder::DecodeToBuffers( 249 uint8** planes, int dst_width, int dst_height) { 250 if (dst_width != GetWidth() || 251 dst_height > GetHeight()) { 252 // ERROR: Bad dimensions 253 return LIBYUV_FALSE; 254 } 255 #ifdef HAVE_SETJMP 256 if (setjmp(error_mgr_->setjmp_buffer)) { 257 // We called into jpeglib, it experienced an error sometime during this 258 // function call, and we called longjmp() and rewound the stack to here. 259 // Return error. 260 return LIBYUV_FALSE; 261 } 262 #endif 263 if (!StartDecode()) { 264 return LIBYUV_FALSE; 265 } 266 SetScanlinePointers(databuf_); 267 int lines_left = dst_height; 268 // Compute amount of lines to skip to implement vertical crop. 269 // TODO(fbarchard): Ensure skip is a multiple of maximum component 270 // subsample. ie 2 271 int skip = (GetHeight() - dst_height) / 2; 272 if (skip > 0) { 273 // There is no API to skip lines in the output data, so we read them 274 // into the temp buffer. 275 while (skip >= GetImageScanlinesPerImcuRow()) { 276 if (!DecodeImcuRow()) { 277 FinishDecode(); 278 return LIBYUV_FALSE; 279 } 280 skip -= GetImageScanlinesPerImcuRow(); 281 } 282 if (skip > 0) { 283 // Have a partial iMCU row left over to skip. Must read it and then 284 // copy the parts we want into the destination. 285 if (!DecodeImcuRow()) { 286 FinishDecode(); 287 return LIBYUV_FALSE; 288 } 289 for (int i = 0; i < num_outbufs_; ++i) { 290 // TODO(fbarchard): Compute skip to avoid this 291 assert(skip % GetVertSubSampFactor(i) == 0); 292 int rows_to_skip = 293 DivideAndRoundDown(skip, GetVertSubSampFactor(i)); 294 int scanlines_to_copy = GetComponentScanlinesPerImcuRow(i) - 295 rows_to_skip; 296 int data_to_skip = rows_to_skip * GetComponentStride(i); 297 CopyPlane(databuf_[i] + data_to_skip, GetComponentStride(i), 298 planes[i], GetComponentWidth(i), 299 GetComponentWidth(i), scanlines_to_copy); 300 planes[i] += scanlines_to_copy * GetComponentWidth(i); 301 } 302 lines_left -= (GetImageScanlinesPerImcuRow() - skip); 303 } 304 } 305 306 // Read full MCUs but cropped horizontally 307 for (; lines_left > GetImageScanlinesPerImcuRow(); 308 lines_left -= GetImageScanlinesPerImcuRow()) { 309 if (!DecodeImcuRow()) { 310 FinishDecode(); 311 return LIBYUV_FALSE; 312 } 313 for (int i = 0; i < num_outbufs_; ++i) { 314 int scanlines_to_copy = GetComponentScanlinesPerImcuRow(i); 315 CopyPlane(databuf_[i], GetComponentStride(i), 316 planes[i], GetComponentWidth(i), 317 GetComponentWidth(i), scanlines_to_copy); 318 planes[i] += scanlines_to_copy * GetComponentWidth(i); 319 } 320 } 321 322 if (lines_left > 0) { 323 // Have a partial iMCU row left over to decode. 324 if (!DecodeImcuRow()) { 325 FinishDecode(); 326 return LIBYUV_FALSE; 327 } 328 for (int i = 0; i < num_outbufs_; ++i) { 329 int scanlines_to_copy = 330 DivideAndRoundUp(lines_left, GetVertSubSampFactor(i)); 331 CopyPlane(databuf_[i], GetComponentStride(i), 332 planes[i], GetComponentWidth(i), 333 GetComponentWidth(i), scanlines_to_copy); 334 planes[i] += scanlines_to_copy * GetComponentWidth(i); 335 } 336 } 337 return FinishDecode(); 338 } 339 340 LIBYUV_BOOL MJpegDecoder::DecodeToCallback(CallbackFunction fn, void* opaque, 341 int dst_width, int dst_height) { 342 if (dst_width != GetWidth() || 343 dst_height > GetHeight()) { 344 // ERROR: Bad dimensions 345 return LIBYUV_FALSE; 346 } 347 #ifdef HAVE_SETJMP 348 if (setjmp(error_mgr_->setjmp_buffer)) { 349 // We called into jpeglib, it experienced an error sometime during this 350 // function call, and we called longjmp() and rewound the stack to here. 351 // Return error. 352 return LIBYUV_FALSE; 353 } 354 #endif 355 if (!StartDecode()) { 356 return LIBYUV_FALSE; 357 } 358 SetScanlinePointers(databuf_); 359 int lines_left = dst_height; 360 // TODO(fbarchard): Compute amount of lines to skip to implement vertical crop 361 int skip = (GetHeight() - dst_height) / 2; 362 if (skip > 0) { 363 while (skip >= GetImageScanlinesPerImcuRow()) { 364 if (!DecodeImcuRow()) { 365 FinishDecode(); 366 return LIBYUV_FALSE; 367 } 368 skip -= GetImageScanlinesPerImcuRow(); 369 } 370 if (skip > 0) { 371 // Have a partial iMCU row left over to skip. 372 if (!DecodeImcuRow()) { 373 FinishDecode(); 374 return LIBYUV_FALSE; 375 } 376 for (int i = 0; i < num_outbufs_; ++i) { 377 // TODO(fbarchard): Compute skip to avoid this 378 assert(skip % GetVertSubSampFactor(i) == 0); 379 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i)); 380 int data_to_skip = rows_to_skip * GetComponentStride(i); 381 // Change our own data buffer pointers so we can pass them to the 382 // callback. 383 databuf_[i] += data_to_skip; 384 } 385 int scanlines_to_copy = GetImageScanlinesPerImcuRow() - skip; 386 (*fn)(opaque, databuf_, databuf_strides_, scanlines_to_copy); 387 // Now change them back. 388 for (int i = 0; i < num_outbufs_; ++i) { 389 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i)); 390 int data_to_skip = rows_to_skip * GetComponentStride(i); 391 databuf_[i] -= data_to_skip; 392 } 393 lines_left -= scanlines_to_copy; 394 } 395 } 396 // Read full MCUs until we get to the crop point. 397 for (; lines_left >= GetImageScanlinesPerImcuRow(); 398 lines_left -= GetImageScanlinesPerImcuRow()) { 399 if (!DecodeImcuRow()) { 400 FinishDecode(); 401 return LIBYUV_FALSE; 402 } 403 (*fn)(opaque, databuf_, databuf_strides_, GetImageScanlinesPerImcuRow()); 404 } 405 if (lines_left > 0) { 406 // Have a partial iMCU row left over to decode. 407 if (!DecodeImcuRow()) { 408 FinishDecode(); 409 return LIBYUV_FALSE; 410 } 411 (*fn)(opaque, databuf_, databuf_strides_, lines_left); 412 } 413 return FinishDecode(); 414 } 415 416 void init_source(j_decompress_ptr cinfo) { 417 fill_input_buffer(cinfo); 418 } 419 420 boolean fill_input_buffer(j_decompress_ptr cinfo) { 421 BufferVector* buf_vec = reinterpret_cast<BufferVector*>(cinfo->client_data); 422 if (buf_vec->pos >= buf_vec->len) { 423 assert(0 && "No more data"); 424 // ERROR: No more data 425 return FALSE; 426 } 427 cinfo->src->next_input_byte = buf_vec->buffers[buf_vec->pos].data; 428 cinfo->src->bytes_in_buffer = buf_vec->buffers[buf_vec->pos].len; 429 ++buf_vec->pos; 430 return TRUE; 431 } 432 433 void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { // NOLINT 434 cinfo->src->next_input_byte += num_bytes; 435 } 436 437 void term_source(j_decompress_ptr cinfo) { 438 // Nothing to do. 439 } 440 441 #ifdef HAVE_SETJMP 442 void ErrorHandler(j_common_ptr cinfo) { 443 // This is called when a jpeglib command experiences an error. Unfortunately 444 // jpeglib's error handling model is not very flexible, because it expects the 445 // error handler to not return--i.e., it wants the program to terminate. To 446 // recover from errors we use setjmp() as shown in their example. setjmp() is 447 // C's implementation for the "call with current continuation" functionality 448 // seen in some functional programming languages. 449 // A formatted message can be output, but is unsafe for release. 450 #ifdef DEBUG 451 char buf[JMSG_LENGTH_MAX]; 452 (*cinfo->err->format_message)(cinfo, buf); 453 // ERROR: Error in jpeglib: buf 454 #endif 455 456 SetJmpErrorMgr* mgr = reinterpret_cast<SetJmpErrorMgr*>(cinfo->err); 457 // This rewinds the call stack to the point of the corresponding setjmp() 458 // and causes it to return (for a second time) with value 1. 459 longjmp(mgr->setjmp_buffer, 1); 460 } 461 462 void OutputHandler(j_common_ptr cinfo) { 463 // Suppress fprintf warnings. 464 } 465 466 #endif // HAVE_SETJMP 467 468 void MJpegDecoder::AllocOutputBuffers(int num_outbufs) { 469 if (num_outbufs != num_outbufs_) { 470 // We could perhaps optimize this case to resize the output buffers without 471 // necessarily having to delete and recreate each one, but it's not worth 472 // it. 473 DestroyOutputBuffers(); 474 475 scanlines_ = new uint8** [num_outbufs]; 476 scanlines_sizes_ = new int[num_outbufs]; 477 databuf_ = new uint8* [num_outbufs]; 478 databuf_strides_ = new int[num_outbufs]; 479 480 for (int i = 0; i < num_outbufs; ++i) { 481 scanlines_[i] = NULL; 482 scanlines_sizes_[i] = 0; 483 databuf_[i] = NULL; 484 databuf_strides_[i] = 0; 485 } 486 487 num_outbufs_ = num_outbufs; 488 } 489 } 490 491 void MJpegDecoder::DestroyOutputBuffers() { 492 for (int i = 0; i < num_outbufs_; ++i) { 493 delete [] scanlines_[i]; 494 delete [] databuf_[i]; 495 } 496 delete [] scanlines_; 497 delete [] databuf_; 498 delete [] scanlines_sizes_; 499 delete [] databuf_strides_; 500 scanlines_ = NULL; 501 databuf_ = NULL; 502 scanlines_sizes_ = NULL; 503 databuf_strides_ = NULL; 504 num_outbufs_ = 0; 505 } 506 507 // JDCT_IFAST and do_block_smoothing improve performance substantially. 508 LIBYUV_BOOL MJpegDecoder::StartDecode() { 509 decompress_struct_->raw_data_out = TRUE; 510 decompress_struct_->dct_method = JDCT_IFAST; // JDCT_ISLOW is default 511 decompress_struct_->dither_mode = JDITHER_NONE; 512 // Not applicable to 'raw': 513 decompress_struct_->do_fancy_upsampling = (boolean)(LIBYUV_FALSE); 514 // Only for buffered mode: 515 decompress_struct_->enable_2pass_quant = (boolean)(LIBYUV_FALSE); 516 // Blocky but fast: 517 decompress_struct_->do_block_smoothing = (boolean)(LIBYUV_FALSE); 518 519 if (!jpeg_start_decompress(decompress_struct_)) { 520 // ERROR: Couldn't start JPEG decompressor"; 521 return LIBYUV_FALSE; 522 } 523 return LIBYUV_TRUE; 524 } 525 526 LIBYUV_BOOL MJpegDecoder::FinishDecode() { 527 // jpeglib considers it an error if we finish without decoding the whole 528 // image, so we call "abort" rather than "finish". 529 jpeg_abort_decompress(decompress_struct_); 530 return LIBYUV_TRUE; 531 } 532 533 void MJpegDecoder::SetScanlinePointers(uint8** data) { 534 for (int i = 0; i < num_outbufs_; ++i) { 535 uint8* data_i = data[i]; 536 for (int j = 0; j < scanlines_sizes_[i]; ++j) { 537 scanlines_[i][j] = data_i; 538 data_i += GetComponentStride(i); 539 } 540 } 541 } 542 543 inline LIBYUV_BOOL MJpegDecoder::DecodeImcuRow() { 544 return (unsigned int)(GetImageScanlinesPerImcuRow()) == 545 jpeg_read_raw_data(decompress_struct_, 546 scanlines_, 547 GetImageScanlinesPerImcuRow()); 548 } 549 550 // The helper function which recognizes the jpeg sub-sampling type. 551 JpegSubsamplingType MJpegDecoder::JpegSubsamplingTypeHelper( 552 int* subsample_x, int* subsample_y, int number_of_components) { 553 if (number_of_components == 3) { // Color images. 554 if (subsample_x[0] == 1 && subsample_y[0] == 1 && 555 subsample_x[1] == 2 && subsample_y[1] == 2 && 556 subsample_x[2] == 2 && subsample_y[2] == 2) { 557 return kJpegYuv420; 558 } else if (subsample_x[0] == 1 && subsample_y[0] == 1 && 559 subsample_x[1] == 2 && subsample_y[1] == 1 && 560 subsample_x[2] == 2 && subsample_y[2] == 1) { 561 return kJpegYuv422; 562 } else if (subsample_x[0] == 1 && subsample_y[0] == 1 && 563 subsample_x[1] == 1 && subsample_y[1] == 1 && 564 subsample_x[2] == 1 && subsample_y[2] == 1) { 565 return kJpegYuv444; 566 } 567 } else if (number_of_components == 1) { // Grey-scale images. 568 if (subsample_x[0] == 1 && subsample_y[0] == 1) { 569 return kJpegYuv400; 570 } 571 } 572 return kJpegUnknown; 573 } 574 575 } // namespace libyuv 576 #endif // HAVE_JPEG 577 578