2 * Copyright 2012 The LibYuv Project Authors. All rights reserved.
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.
11 #include "libyuv/mjpeg_decoder.h"
16 #if !defined(__pnacl__) && !defined(__CLR_VER) && \
17 !defined(COVERAGE_ENABLED) && !defined(TARGET_IPHONE_SIMULATOR)
18 // Must be included before jpeglib.
22 struct FILE; // For jpeglib.h.
24 // C++ build requires extern C for jpeg internals.
35 #include "libyuv/planar_functions.h" // For CopyPlane().
40 struct SetJmpErrorMgr {
41 jpeg_error_mgr base; // Must be at the top
42 jmp_buf setjmp_buffer;
46 const int MJpegDecoder::kColorSpaceUnknown = JCS_UNKNOWN;
47 const int MJpegDecoder::kColorSpaceGrayscale = JCS_GRAYSCALE;
48 const int MJpegDecoder::kColorSpaceRgb = JCS_RGB;
49 const int MJpegDecoder::kColorSpaceYCbCr = JCS_YCbCr;
50 const int MJpegDecoder::kColorSpaceCMYK = JCS_CMYK;
51 const int MJpegDecoder::kColorSpaceYCCK = JCS_YCCK;
53 // Methods that are passed to jpeglib.
54 boolean fill_input_buffer(jpeg_decompress_struct* cinfo);
55 void init_source(jpeg_decompress_struct* cinfo);
56 void skip_input_data(jpeg_decompress_struct* cinfo,
57 long num_bytes); // NOLINT
58 void term_source(jpeg_decompress_struct* cinfo);
59 void ErrorHandler(jpeg_common_struct* cinfo);
61 MJpegDecoder::MJpegDecoder()
62 : has_scanline_padding_(LIBYUV_FALSE),
65 scanlines_sizes_(NULL),
67 databuf_strides_(NULL) {
68 decompress_struct_ = new jpeg_decompress_struct;
69 source_mgr_ = new jpeg_source_mgr;
71 error_mgr_ = new SetJmpErrorMgr;
72 decompress_struct_->err = jpeg_std_error(&error_mgr_->base);
73 // Override standard exit()-based error handler.
74 error_mgr_->base.error_exit = &ErrorHandler;
76 decompress_struct_->client_data = NULL;
77 source_mgr_->init_source = &init_source;
78 source_mgr_->fill_input_buffer = &fill_input_buffer;
79 source_mgr_->skip_input_data = &skip_input_data;
80 source_mgr_->resync_to_restart = &jpeg_resync_to_restart;
81 source_mgr_->term_source = &term_source;
82 jpeg_create_decompress(decompress_struct_);
83 decompress_struct_->src = source_mgr_;
84 buf_vec_.buffers = &buf_;
88 MJpegDecoder::~MJpegDecoder() {
89 jpeg_destroy_decompress(decompress_struct_);
90 delete decompress_struct_;
95 DestroyOutputBuffers();
98 LIBYUV_BOOL MJpegDecoder::LoadFrame(const uint8* src, size_t src_len) {
99 if (!ValidateJpeg(src, src_len)) {
104 buf_.len = static_cast<int>(src_len);
106 decompress_struct_->client_data = &buf_vec_;
108 if (setjmp(error_mgr_->setjmp_buffer)) {
109 // We called jpeg_read_header, it experienced an error, and we called
110 // longjmp() and rewound the stack to here. Return error.
114 if (jpeg_read_header(decompress_struct_, TRUE) != JPEG_HEADER_OK) {
115 // ERROR: Bad MJPEG header
118 AllocOutputBuffers(GetNumComponents());
119 for (int i = 0; i < num_outbufs_; ++i) {
120 int scanlines_size = GetComponentScanlinesPerImcuRow(i);
121 if (scanlines_sizes_[i] != scanlines_size) {
123 delete scanlines_[i];
125 scanlines_[i] = new uint8* [scanlines_size];
126 scanlines_sizes_[i] = scanlines_size;
129 // We allocate padding for the final scanline to pad it up to DCTSIZE bytes
130 // to avoid memory errors, since jpeglib only reads full MCUs blocks. For
131 // the preceding scanlines, the padding is not needed/wanted because the
132 // following addresses will already be valid (they are the initial bytes of
133 // the next scanline) and will be overwritten when jpeglib writes out that
135 int databuf_stride = GetComponentStride(i);
136 int databuf_size = scanlines_size * databuf_stride;
137 if (databuf_strides_[i] != databuf_stride) {
141 databuf_[i] = new uint8[databuf_size];
142 databuf_strides_[i] = databuf_stride;
145 if (GetComponentStride(i) != GetComponentWidth(i)) {
146 has_scanline_padding_ = LIBYUV_TRUE;
152 static int DivideAndRoundUp(int numerator, int denominator) {
153 return (numerator + denominator - 1) / denominator;
156 static int DivideAndRoundDown(int numerator, int denominator) {
157 return numerator / denominator;
160 // Returns width of the last loaded frame.
161 int MJpegDecoder::GetWidth() {
162 return decompress_struct_->image_width;
165 // Returns height of the last loaded frame.
166 int MJpegDecoder::GetHeight() {
167 return decompress_struct_->image_height;
170 // Returns format of the last loaded frame. The return value is one of the
171 // kColorSpace* constants.
172 int MJpegDecoder::GetColorSpace() {
173 return decompress_struct_->jpeg_color_space;
176 // Number of color components in the color space.
177 int MJpegDecoder::GetNumComponents() {
178 return decompress_struct_->num_components;
181 // Sample factors of the n-th component.
182 int MJpegDecoder::GetHorizSampFactor(int component) {
183 return decompress_struct_->comp_info[component].h_samp_factor;
186 int MJpegDecoder::GetVertSampFactor(int component) {
187 return decompress_struct_->comp_info[component].v_samp_factor;
190 int MJpegDecoder::GetHorizSubSampFactor(int component) {
191 return decompress_struct_->max_h_samp_factor /
192 GetHorizSampFactor(component);
195 int MJpegDecoder::GetVertSubSampFactor(int component) {
196 return decompress_struct_->max_v_samp_factor /
197 GetVertSampFactor(component);
200 int MJpegDecoder::GetImageScanlinesPerImcuRow() {
201 return decompress_struct_->max_v_samp_factor * DCTSIZE;
204 int MJpegDecoder::GetComponentScanlinesPerImcuRow(int component) {
205 int vs = GetVertSubSampFactor(component);
206 return DivideAndRoundUp(GetImageScanlinesPerImcuRow(), vs);
209 int MJpegDecoder::GetComponentWidth(int component) {
210 int hs = GetHorizSubSampFactor(component);
211 return DivideAndRoundUp(GetWidth(), hs);
214 int MJpegDecoder::GetComponentHeight(int component) {
215 int vs = GetVertSubSampFactor(component);
216 return DivideAndRoundUp(GetHeight(), vs);
219 // Get width in bytes padded out to a multiple of DCTSIZE
220 int MJpegDecoder::GetComponentStride(int component) {
221 return (GetComponentWidth(component) + DCTSIZE - 1) & ~(DCTSIZE - 1);
224 int MJpegDecoder::GetComponentSize(int component) {
225 return GetComponentWidth(component) * GetComponentHeight(component);
228 LIBYUV_BOOL MJpegDecoder::UnloadFrame() {
230 if (setjmp(error_mgr_->setjmp_buffer)) {
231 // We called jpeg_abort_decompress, it experienced an error, and we called
232 // longjmp() and rewound the stack to here. Return error.
236 jpeg_abort_decompress(decompress_struct_);
240 // TODO(fbarchard): Allow rectangle to be specified: x, y, width, height.
241 LIBYUV_BOOL MJpegDecoder::DecodeToBuffers(
242 uint8** planes, int dst_width, int dst_height) {
243 if (dst_width != GetWidth() ||
244 dst_height > GetHeight()) {
245 // ERROR: Bad dimensions
249 if (setjmp(error_mgr_->setjmp_buffer)) {
250 // We called into jpeglib, it experienced an error sometime during this
251 // function call, and we called longjmp() and rewound the stack to here.
256 if (!StartDecode()) {
259 SetScanlinePointers(databuf_);
260 int lines_left = dst_height;
261 // Compute amount of lines to skip to implement vertical crop.
262 // TODO(fbarchard): Ensure skip is a multiple of maximum component
264 int skip = (GetHeight() - dst_height) / 2;
266 // There is no API to skip lines in the output data, so we read them
267 // into the temp buffer.
268 while (skip >= GetImageScanlinesPerImcuRow()) {
269 if (!DecodeImcuRow()) {
273 skip -= GetImageScanlinesPerImcuRow();
276 // Have a partial iMCU row left over to skip. Must read it and then
277 // copy the parts we want into the destination.
278 if (!DecodeImcuRow()) {
282 for (int i = 0; i < num_outbufs_; ++i) {
283 // TODO(fbarchard): Compute skip to avoid this
284 assert(skip % GetVertSubSampFactor(i) == 0);
286 DivideAndRoundDown(skip, GetVertSubSampFactor(i));
287 int scanlines_to_copy = GetComponentScanlinesPerImcuRow(i) -
289 int data_to_skip = rows_to_skip * GetComponentStride(i);
290 CopyPlane(databuf_[i] + data_to_skip, GetComponentStride(i),
291 planes[i], GetComponentWidth(i),
292 GetComponentWidth(i), scanlines_to_copy);
293 planes[i] += scanlines_to_copy * GetComponentWidth(i);
295 lines_left -= (GetImageScanlinesPerImcuRow() - skip);
299 // Read full MCUs but cropped horizontally
300 for (; lines_left > GetImageScanlinesPerImcuRow();
301 lines_left -= GetImageScanlinesPerImcuRow()) {
302 if (!DecodeImcuRow()) {
306 for (int i = 0; i < num_outbufs_; ++i) {
307 int scanlines_to_copy = GetComponentScanlinesPerImcuRow(i);
308 CopyPlane(databuf_[i], GetComponentStride(i),
309 planes[i], GetComponentWidth(i),
310 GetComponentWidth(i), scanlines_to_copy);
311 planes[i] += scanlines_to_copy * GetComponentWidth(i);
315 if (lines_left > 0) {
316 // Have a partial iMCU row left over to decode.
317 if (!DecodeImcuRow()) {
321 for (int i = 0; i < num_outbufs_; ++i) {
322 int scanlines_to_copy =
323 DivideAndRoundUp(lines_left, GetVertSubSampFactor(i));
324 CopyPlane(databuf_[i], GetComponentStride(i),
325 planes[i], GetComponentWidth(i),
326 GetComponentWidth(i), scanlines_to_copy);
327 planes[i] += scanlines_to_copy * GetComponentWidth(i);
330 return FinishDecode();
333 LIBYUV_BOOL MJpegDecoder::DecodeToCallback(CallbackFunction fn, void* opaque,
334 int dst_width, int dst_height) {
335 if (dst_width != GetWidth() ||
336 dst_height > GetHeight()) {
337 // ERROR: Bad dimensions
341 if (setjmp(error_mgr_->setjmp_buffer)) {
342 // We called into jpeglib, it experienced an error sometime during this
343 // function call, and we called longjmp() and rewound the stack to here.
348 if (!StartDecode()) {
351 SetScanlinePointers(databuf_);
352 int lines_left = dst_height;
353 // TODO(fbarchard): Compute amount of lines to skip to implement vertical crop
354 int skip = (GetHeight() - dst_height) / 2;
356 while (skip >= GetImageScanlinesPerImcuRow()) {
357 if (!DecodeImcuRow()) {
361 skip -= GetImageScanlinesPerImcuRow();
364 // Have a partial iMCU row left over to skip.
365 if (!DecodeImcuRow()) {
369 for (int i = 0; i < num_outbufs_; ++i) {
370 // TODO(fbarchard): Compute skip to avoid this
371 assert(skip % GetVertSubSampFactor(i) == 0);
372 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i));
373 int data_to_skip = rows_to_skip * GetComponentStride(i);
374 // Change our own data buffer pointers so we can pass them to the
376 databuf_[i] += data_to_skip;
378 int scanlines_to_copy = GetImageScanlinesPerImcuRow() - skip;
379 (*fn)(opaque, databuf_, databuf_strides_, scanlines_to_copy);
380 // Now change them back.
381 for (int i = 0; i < num_outbufs_; ++i) {
382 int rows_to_skip = DivideAndRoundDown(skip, GetVertSubSampFactor(i));
383 int data_to_skip = rows_to_skip * GetComponentStride(i);
384 databuf_[i] -= data_to_skip;
386 lines_left -= scanlines_to_copy;
389 // Read full MCUs until we get to the crop point.
390 for (; lines_left >= GetImageScanlinesPerImcuRow();
391 lines_left -= GetImageScanlinesPerImcuRow()) {
392 if (!DecodeImcuRow()) {
396 (*fn)(opaque, databuf_, databuf_strides_, GetImageScanlinesPerImcuRow());
398 if (lines_left > 0) {
399 // Have a partial iMCU row left over to decode.
400 if (!DecodeImcuRow()) {
404 (*fn)(opaque, databuf_, databuf_strides_, lines_left);
406 return FinishDecode();
409 void init_source(j_decompress_ptr cinfo) {
410 fill_input_buffer(cinfo);
413 boolean fill_input_buffer(j_decompress_ptr cinfo) {
414 BufferVector* buf_vec = reinterpret_cast<BufferVector*>(cinfo->client_data);
415 if (buf_vec->pos >= buf_vec->len) {
416 assert(0 && "No more data");
417 // ERROR: No more data
420 cinfo->src->next_input_byte = buf_vec->buffers[buf_vec->pos].data;
421 cinfo->src->bytes_in_buffer = buf_vec->buffers[buf_vec->pos].len;
426 void skip_input_data(j_decompress_ptr cinfo,
427 long num_bytes) { // NOLINT
428 cinfo->src->next_input_byte += num_bytes;
431 void term_source(j_decompress_ptr cinfo) {
436 void ErrorHandler(j_common_ptr cinfo) {
437 // This is called when a jpeglib command experiences an error. Unfortunately
438 // jpeglib's error handling model is not very flexible, because it expects the
439 // error handler to not return--i.e., it wants the program to terminate. To
440 // recover from errors we use setjmp() as shown in their example. setjmp() is
441 // C's implementation for the "call with current continuation" functionality
442 // seen in some functional programming languages.
443 // A formatted message can be output, but is unsafe for release.
445 char buf[JMSG_LENGTH_MAX];
446 (*cinfo->err->format_message)(cinfo, buf);
447 // ERROR: Error in jpeglib: buf
450 SetJmpErrorMgr* mgr = reinterpret_cast<SetJmpErrorMgr*>(cinfo->err);
451 // This rewinds the call stack to the point of the corresponding setjmp()
452 // and causes it to return (for a second time) with value 1.
453 longjmp(mgr->setjmp_buffer, 1);
457 void MJpegDecoder::AllocOutputBuffers(int num_outbufs) {
458 if (num_outbufs != num_outbufs_) {
459 // We could perhaps optimize this case to resize the output buffers without
460 // necessarily having to delete and recreate each one, but it's not worth
462 DestroyOutputBuffers();
464 scanlines_ = new uint8** [num_outbufs];
465 scanlines_sizes_ = new int[num_outbufs];
466 databuf_ = new uint8* [num_outbufs];
467 databuf_strides_ = new int[num_outbufs];
469 for (int i = 0; i < num_outbufs; ++i) {
470 scanlines_[i] = NULL;
471 scanlines_sizes_[i] = 0;
473 databuf_strides_[i] = 0;
476 num_outbufs_ = num_outbufs;
480 void MJpegDecoder::DestroyOutputBuffers() {
481 for (int i = 0; i < num_outbufs_; ++i) {
482 delete [] scanlines_[i];
483 delete [] databuf_[i];
485 delete [] scanlines_;
487 delete [] scanlines_sizes_;
488 delete [] databuf_strides_;
491 scanlines_sizes_ = NULL;
492 databuf_strides_ = NULL;
496 // JDCT_IFAST and do_block_smoothing improve performance substantially.
497 LIBYUV_BOOL MJpegDecoder::StartDecode() {
498 decompress_struct_->raw_data_out = TRUE;
499 decompress_struct_->dct_method = JDCT_IFAST; // JDCT_ISLOW is default
500 decompress_struct_->dither_mode = JDITHER_NONE;
501 // Not applicable to 'raw':
502 decompress_struct_->do_fancy_upsampling = (boolean)(LIBYUV_FALSE);
503 // Only for buffered mode:
504 decompress_struct_->enable_2pass_quant = (boolean)(LIBYUV_FALSE);
506 decompress_struct_->do_block_smoothing = (boolean)(LIBYUV_FALSE);
508 if (!jpeg_start_decompress(decompress_struct_)) {
509 // ERROR: Couldn't start JPEG decompressor";
515 LIBYUV_BOOL MJpegDecoder::FinishDecode() {
516 // jpeglib considers it an error if we finish without decoding the whole
517 // image, so we call "abort" rather than "finish".
518 jpeg_abort_decompress(decompress_struct_);
522 void MJpegDecoder::SetScanlinePointers(uint8** data) {
523 for (int i = 0; i < num_outbufs_; ++i) {
524 uint8* data_i = data[i];
525 for (int j = 0; j < scanlines_sizes_[i]; ++j) {
526 scanlines_[i][j] = data_i;
527 data_i += GetComponentStride(i);
532 inline LIBYUV_BOOL MJpegDecoder::DecodeImcuRow() {
533 return (unsigned int)(GetImageScanlinesPerImcuRow()) ==
534 jpeg_read_raw_data(decompress_struct_,
536 GetImageScanlinesPerImcuRow());
539 // The helper function which recognizes the jpeg sub-sampling type.
540 JpegSubsamplingType MJpegDecoder::JpegSubsamplingTypeHelper(
541 int* subsample_x, int* subsample_y, int number_of_components) {
542 if (number_of_components == 3) { // Color images.
543 if (subsample_x[0] == 1 && subsample_y[0] == 1 &&
544 subsample_x[1] == 2 && subsample_y[1] == 2 &&
545 subsample_x[2] == 2 && subsample_y[2] == 2) {
547 } else if (subsample_x[0] == 1 && subsample_y[0] == 1 &&
548 subsample_x[1] == 2 && subsample_y[1] == 1 &&
549 subsample_x[2] == 2 && subsample_y[2] == 1) {
551 } else if (subsample_x[0] == 1 && subsample_y[0] == 1 &&
552 subsample_x[1] == 1 && subsample_y[1] == 1 &&
553 subsample_x[2] == 1 && subsample_y[2] == 1) {
556 } else if (number_of_components == 1) { // Grey-scale images.
557 if (subsample_x[0] == 1 && subsample_y[0] == 1) {
564 } // namespace libyuv