Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libyuv / source / mjpeg_decoder.cc
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 #endif
22 struct FILE;  // For jpeglib.h.
23
24 // C++ build requires extern C for jpeg internals.
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 #include <jpeglib.h>
30
31 #ifdef __cplusplus
32 }  // extern "C"
33 #endif
34
35 #include "libyuv/planar_functions.h"  // For CopyPlane().
36
37 namespace libyuv {
38
39 #ifdef HAVE_SETJMP
40 struct SetJmpErrorMgr {
41   jpeg_error_mgr base;  // Must be at the top
42   jmp_buf setjmp_buffer;
43 };
44 #endif
45
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;
52
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);
60
61 MJpegDecoder::MJpegDecoder()
62     : has_scanline_padding_(LIBYUV_FALSE),
63       num_outbufs_(0),
64       scanlines_(NULL),
65       scanlines_sizes_(NULL),
66       databuf_(NULL),
67       databuf_strides_(NULL) {
68   decompress_struct_ = new jpeg_decompress_struct;
69   source_mgr_ = new jpeg_source_mgr;
70 #ifdef HAVE_SETJMP
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;
75 #endif
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_;
85   buf_vec_.len = 1;
86 }
87
88 MJpegDecoder::~MJpegDecoder() {
89   jpeg_destroy_decompress(decompress_struct_);
90   delete decompress_struct_;
91   delete source_mgr_;
92 #ifdef HAVE_SETJMP
93   delete error_mgr_;
94 #endif
95   DestroyOutputBuffers();
96 }
97
98 LIBYUV_BOOL MJpegDecoder::LoadFrame(const uint8* src, size_t src_len) {
99   if (!ValidateJpeg(src, src_len)) {
100     return LIBYUV_FALSE;
101   }
102
103   buf_.data = src;
104   buf_.len = static_cast<int>(src_len);
105   buf_vec_.pos = 0;
106   decompress_struct_->client_data = &buf_vec_;
107 #ifdef HAVE_SETJMP
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.
111     return LIBYUV_FALSE;
112   }
113 #endif
114   if (jpeg_read_header(decompress_struct_, TRUE) != JPEG_HEADER_OK) {
115     // ERROR: Bad MJPEG header
116     return LIBYUV_FALSE;
117   }
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) {
122       if (scanlines_[i]) {
123         delete scanlines_[i];
124       }
125       scanlines_[i] = new uint8* [scanlines_size];
126       scanlines_sizes_[i] = scanlines_size;
127     }
128
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
134     // next scanline.
135     int databuf_stride = GetComponentStride(i);
136     int databuf_size = scanlines_size * databuf_stride;
137     if (databuf_strides_[i] != databuf_stride) {
138       if (databuf_[i]) {
139         delete databuf_[i];
140       }
141       databuf_[i] = new uint8[databuf_size];
142       databuf_strides_[i] = databuf_stride;
143     }
144
145     if (GetComponentStride(i) != GetComponentWidth(i)) {
146       has_scanline_padding_ = LIBYUV_TRUE;
147     }
148   }
149   return LIBYUV_TRUE;
150 }
151
152 static int DivideAndRoundUp(int numerator, int denominator) {
153   return (numerator + denominator - 1) / denominator;
154 }
155
156 static int DivideAndRoundDown(int numerator, int denominator) {
157   return numerator / denominator;
158 }
159
160 // Returns width of the last loaded frame.
161 int MJpegDecoder::GetWidth() {
162   return decompress_struct_->image_width;
163 }
164
165 // Returns height of the last loaded frame.
166 int MJpegDecoder::GetHeight() {
167   return decompress_struct_->image_height;
168 }
169
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;
174 }
175
176 // Number of color components in the color space.
177 int MJpegDecoder::GetNumComponents() {
178   return decompress_struct_->num_components;
179 }
180
181 // Sample factors of the n-th component.
182 int MJpegDecoder::GetHorizSampFactor(int component) {
183   return decompress_struct_->comp_info[component].h_samp_factor;
184 }
185
186 int MJpegDecoder::GetVertSampFactor(int component) {
187   return decompress_struct_->comp_info[component].v_samp_factor;
188 }
189
190 int MJpegDecoder::GetHorizSubSampFactor(int component) {
191   return decompress_struct_->max_h_samp_factor /
192       GetHorizSampFactor(component);
193 }
194
195 int MJpegDecoder::GetVertSubSampFactor(int component) {
196   return decompress_struct_->max_v_samp_factor /
197       GetVertSampFactor(component);
198 }
199
200 int MJpegDecoder::GetImageScanlinesPerImcuRow() {
201   return decompress_struct_->max_v_samp_factor * DCTSIZE;
202 }
203
204 int MJpegDecoder::GetComponentScanlinesPerImcuRow(int component) {
205   int vs = GetVertSubSampFactor(component);
206   return DivideAndRoundUp(GetImageScanlinesPerImcuRow(), vs);
207 }
208
209 int MJpegDecoder::GetComponentWidth(int component) {
210   int hs = GetHorizSubSampFactor(component);
211   return DivideAndRoundUp(GetWidth(), hs);
212 }
213
214 int MJpegDecoder::GetComponentHeight(int component) {
215   int vs = GetVertSubSampFactor(component);
216   return DivideAndRoundUp(GetHeight(), vs);
217 }
218
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);
222 }
223
224 int MJpegDecoder::GetComponentSize(int component) {
225   return GetComponentWidth(component) * GetComponentHeight(component);
226 }
227
228 LIBYUV_BOOL MJpegDecoder::UnloadFrame() {
229 #ifdef HAVE_SETJMP
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.
233     return LIBYUV_FALSE;
234   }
235 #endif
236   jpeg_abort_decompress(decompress_struct_);
237   return LIBYUV_TRUE;
238 }
239
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
246     return LIBYUV_FALSE;
247   }
248 #ifdef HAVE_SETJMP
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.
252     // Return error.
253     return LIBYUV_FALSE;
254   }
255 #endif
256   if (!StartDecode()) {
257     return LIBYUV_FALSE;
258   }
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
263   // subsample. ie 2
264   int skip = (GetHeight() - dst_height) / 2;
265   if (skip > 0) {
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()) {
270         FinishDecode();
271         return LIBYUV_FALSE;
272       }
273       skip -= GetImageScanlinesPerImcuRow();
274     }
275     if (skip > 0) {
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()) {
279         FinishDecode();
280         return LIBYUV_FALSE;
281       }
282       for (int i = 0; i < num_outbufs_; ++i) {
283         // TODO(fbarchard): Compute skip to avoid this
284         assert(skip % GetVertSubSampFactor(i) == 0);
285         int rows_to_skip =
286             DivideAndRoundDown(skip, GetVertSubSampFactor(i));
287         int scanlines_to_copy = GetComponentScanlinesPerImcuRow(i) -
288                                 rows_to_skip;
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);
294       }
295       lines_left -= (GetImageScanlinesPerImcuRow() - skip);
296     }
297   }
298
299   // Read full MCUs but cropped horizontally
300   for (; lines_left > GetImageScanlinesPerImcuRow();
301          lines_left -= GetImageScanlinesPerImcuRow()) {
302     if (!DecodeImcuRow()) {
303       FinishDecode();
304       return LIBYUV_FALSE;
305     }
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);
312     }
313   }
314
315   if (lines_left > 0) {
316     // Have a partial iMCU row left over to decode.
317     if (!DecodeImcuRow()) {
318       FinishDecode();
319       return LIBYUV_FALSE;
320     }
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);
328     }
329   }
330   return FinishDecode();
331 }
332
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
338     return LIBYUV_FALSE;
339   }
340 #ifdef HAVE_SETJMP
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.
344     // Return error.
345     return LIBYUV_FALSE;
346   }
347 #endif
348   if (!StartDecode()) {
349     return LIBYUV_FALSE;
350   }
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;
355   if (skip > 0) {
356     while (skip >= GetImageScanlinesPerImcuRow()) {
357       if (!DecodeImcuRow()) {
358         FinishDecode();
359         return LIBYUV_FALSE;
360       }
361       skip -= GetImageScanlinesPerImcuRow();
362     }
363     if (skip > 0) {
364       // Have a partial iMCU row left over to skip.
365       if (!DecodeImcuRow()) {
366         FinishDecode();
367         return LIBYUV_FALSE;
368       }
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
375         // callback.
376         databuf_[i] += data_to_skip;
377       }
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;
385       }
386       lines_left -= scanlines_to_copy;
387     }
388   }
389   // Read full MCUs until we get to the crop point.
390   for (; lines_left >= GetImageScanlinesPerImcuRow();
391          lines_left -= GetImageScanlinesPerImcuRow()) {
392     if (!DecodeImcuRow()) {
393       FinishDecode();
394       return LIBYUV_FALSE;
395     }
396     (*fn)(opaque, databuf_, databuf_strides_, GetImageScanlinesPerImcuRow());
397   }
398   if (lines_left > 0) {
399     // Have a partial iMCU row left over to decode.
400     if (!DecodeImcuRow()) {
401       FinishDecode();
402       return LIBYUV_FALSE;
403     }
404     (*fn)(opaque, databuf_, databuf_strides_, lines_left);
405   }
406   return FinishDecode();
407 }
408
409 void init_source(j_decompress_ptr cinfo) {
410   fill_input_buffer(cinfo);
411 }
412
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
418     return FALSE;
419   }
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;
422   ++buf_vec->pos;
423   return TRUE;
424 }
425
426 void skip_input_data(j_decompress_ptr cinfo,
427                      long num_bytes) {  // NOLINT
428   cinfo->src->next_input_byte += num_bytes;
429 }
430
431 void term_source(j_decompress_ptr cinfo) {
432   // Nothing to do.
433 }
434
435 #ifdef HAVE_SETJMP
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.
444 #ifdef DEBUG
445   char buf[JMSG_LENGTH_MAX];
446   (*cinfo->err->format_message)(cinfo, buf);
447   // ERROR: Error in jpeglib: buf
448 #endif
449
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);
454 }
455 #endif
456
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
461     // it.
462     DestroyOutputBuffers();
463
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];
468
469     for (int i = 0; i < num_outbufs; ++i) {
470       scanlines_[i] = NULL;
471       scanlines_sizes_[i] = 0;
472       databuf_[i] = NULL;
473       databuf_strides_[i] = 0;
474     }
475
476     num_outbufs_ = num_outbufs;
477   }
478 }
479
480 void MJpegDecoder::DestroyOutputBuffers() {
481   for (int i = 0; i < num_outbufs_; ++i) {
482     delete [] scanlines_[i];
483     delete [] databuf_[i];
484   }
485   delete [] scanlines_;
486   delete [] databuf_;
487   delete [] scanlines_sizes_;
488   delete [] databuf_strides_;
489   scanlines_ = NULL;
490   databuf_ = NULL;
491   scanlines_sizes_ = NULL;
492   databuf_strides_ = NULL;
493   num_outbufs_ = 0;
494 }
495
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);
505   // Blocky but fast:
506   decompress_struct_->do_block_smoothing = (boolean)(LIBYUV_FALSE);
507
508   if (!jpeg_start_decompress(decompress_struct_)) {
509     // ERROR: Couldn't start JPEG decompressor";
510     return LIBYUV_FALSE;
511   }
512   return LIBYUV_TRUE;
513 }
514
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_);
519   return LIBYUV_TRUE;
520 }
521
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);
528     }
529   }
530 }
531
532 inline LIBYUV_BOOL MJpegDecoder::DecodeImcuRow() {
533   return (unsigned int)(GetImageScanlinesPerImcuRow()) ==
534       jpeg_read_raw_data(decompress_struct_,
535                          scanlines_,
536                          GetImageScanlinesPerImcuRow());
537 }
538
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) {
546       return kJpegYuv420;
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) {
550       return kJpegYuv422;
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) {
554       return kJpegYuv444;
555     }
556   } else if (number_of_components == 1) {  // Grey-scale images.
557     if (subsample_x[0] == 1 && subsample_y[0] == 1) {
558       return kJpegYuv400;
559     }
560   }
561   return kJpegUnknown;
562 }
563
564 }  // namespace libyuv
565 #endif  // HAVE_JPEG
566