Merge "Add ashmem implementation for libjpeg decoder's backing store" into gingerbread
diff --git a/jdapistd.c b/jdapistd.c
index 42060c4..e1233df 100644
--- a/jdapistd.c
+++ b/jdapistd.c
@@ -204,7 +204,8 @@
  * Initialize the jpeg decoder to decompressing a rectangle with size of (width, height)
  * and its upper-left corner located at (start_x, start_y).
  * Align start_x and start_y to multiplies of iMCU width and height, respectively.
- * Also, the new reader position will be returned in (start_x, start_y).
+ * Also, the new reader position and sampled image size will be returned in
+ * (start_x, start_y) and (width, height), respectively.
  */
 
 GLOBAL(void)
@@ -217,15 +218,18 @@
   int row_offset = *start_y / lines_per_iMCU_row;
   int col_left_boundary = ((*start_x / lines_per_iMCU_col)
             / index->MCU_sample_size) * index->MCU_sample_size;
-  int col_right_boundary = (*start_x + *width + lines_per_iMCU_col - 1)
-            / lines_per_iMCU_col;
+  int col_right_boundary =
+                  jdiv_round_up(*start_x + *width, lines_per_iMCU_col);
+
+  cinfo->coef->MCU_columns_to_skip =
+      *start_x / lines_per_iMCU_col - col_left_boundary;
 
   *height = (*start_y - row_offset * lines_per_iMCU_row) + *height;
   *start_x = col_left_boundary * lines_per_iMCU_col;
   *start_y = row_offset * lines_per_iMCU_row;
-  cinfo->image_width = jmin(cinfo->original_image_width -
-          col_left_boundary * lines_per_iMCU_col,
-          (col_right_boundary - col_left_boundary) * lines_per_iMCU_col);
+  cinfo->image_width = jmin(cinfo->original_image_width,
+          col_right_boundary * lines_per_iMCU_col) -
+          col_left_boundary * lines_per_iMCU_col;
   cinfo->input_iMCU_row = row_offset;
   cinfo->output_iMCU_row = row_offset;
 
@@ -239,10 +243,11 @@
   else
     jpeg_decompress_per_scan_setup(cinfo);
 
-  int sampleSize = cinfo->image_width / cinfo->output_width;
-  *height /= sampleSize;
+  int sample_size = DCTSIZE / cinfo->min_DCT_scaled_size;
+
+  *height = jdiv_round_up(*height, sample_size);
   *width = cinfo->output_width;
-  cinfo->output_scanline = lines_per_iMCU_row * row_offset / sampleSize;
+  cinfo->output_scanline = lines_per_iMCU_row * row_offset / sample_size;
   cinfo->inputctl->consume_input = cinfo->coef->consume_data;
   cinfo->inputctl->consume_input_build_huffman_index =
       cinfo->coef->consume_data_build_huffman_index;
@@ -265,24 +270,23 @@
 
 GLOBAL(JDIMENSION)
 jpeg_read_tile_scanline (j_decompress_ptr cinfo, huffman_index *index,
-        JSAMPARRAY scanlines, int start_x, int start_y, int width, int height)
+        JSAMPARRAY scanlines)
 {
   // Calculates the boundary of iMCU
   int lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
   int lines_per_iMCU_col = cinfo->max_h_samp_factor * DCTSIZE;
-  int col_left_boundary = ((start_x / lines_per_iMCU_col)
-          / index->MCU_sample_size) * index->MCU_sample_size;
-  int sampleSize = cinfo->image_width / cinfo->output_width;
-  int row_ctr = 0;
+  int sample_size = DCTSIZE / cinfo->min_DCT_scaled_size;
+  JDIMENSION row_ctr = 0;
 
   if (cinfo->progressive_mode) {
     (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, 1);
   } else {
-    if (cinfo->output_scanline % (lines_per_iMCU_row / sampleSize) == 0) {
+    if (cinfo->output_scanline % (lines_per_iMCU_row / sample_size) == 0) {
       // Set the read head to the next iMCU row
       int iMCU_row_offset = cinfo->output_scanline /
-            (lines_per_iMCU_row / sampleSize);
-      int offset_data_col_position = col_left_boundary / index->MCU_sample_size;
+            (lines_per_iMCU_row / sample_size);
+      int offset_data_col_position = cinfo->coef->MCU_column_left_boundary /
+            index->MCU_sample_size;
       huffman_offset_data offset_data =
           index->scan[0].offset[iMCU_row_offset][offset_data_col_position];
       (*cinfo->entropy->configure_huffman_decoder) (cinfo, offset_data);
diff --git a/jdcoefct.c b/jdcoefct.c
index 7a9f993..9e8040b 100644
--- a/jdcoefct.c
+++ b/jdcoefct.c
@@ -170,13 +170,18 @@
     for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
 	 MCU_col_num++) {
       /* Try to fetch an MCU.  Entropy decoder expects buffer to be zeroed. */
-      jzero_far((void FAR *) coef->MCU_buffer[0],
+      if (MCU_col_num < coef->pub.MCU_columns_to_skip) {
+        (*cinfo->entropy->decode_mcu_discard_coef) (cinfo);
+        continue;
+      } else {
+        jzero_far((void FAR *) coef->MCU_buffer[0],
 		(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
-      if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
-	/* Suspension forced; update state counters and exit */
-	coef->MCU_vert_offset = yoffset;
-	coef->MCU_ctr = MCU_col_num;
-	return JPEG_SUSPENDED;
+        if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+	  /* Suspension forced; update state counters and exit */
+	  coef->MCU_vert_offset = yoffset;
+	  coef->MCU_ctr = MCU_col_num;
+	  return JPEG_SUSPENDED;
+        }
       }
       /* Determine where data should go in output_buf and do the IDCT thing.
        * We skip dummy blocks at the right and bottom edges (but blkn gets
@@ -203,8 +208,8 @@
 	    output_col = start_col;
 	    for (xindex = 0; xindex < useful_width; xindex++) {
 	      (*inverse_DCT) (cinfo, compptr,
-			      (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
-			      output_ptr, output_col);
+		        (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+		        output_ptr, output_col);
 	      output_col += compptr->DCT_scaled_size;
 	    }
 	  }
@@ -272,10 +277,9 @@
   unsigned int MCUs_per_row = cinfo->MCUs_per_row;
 #ifdef ANDROID_TILE_BASED_DECODE
   if (cinfo->tile_decode) {
-    MCUs_per_row =
+    MCUs_per_row = jmin(MCUs_per_row,
         (cinfo->coef->column_right_boundary - cinfo->coef->column_left_boundary)
-        * cinfo->entropy->index->MCU_sample_size * cinfo->max_h_samp_factor;
-    MCUs_per_row = jmin(MCUs_per_row, cinfo->MCUs_per_row);
+        * cinfo->entropy->index->MCU_sample_size * cinfo->max_h_samp_factor);
   }
 #endif
 
@@ -576,11 +580,25 @@
     }
     inverse_DCT = cinfo->idct->inverse_DCT[ci];
     output_ptr = output_buf[ci];
+    int width_in_blocks = compptr->width_in_blocks;
+    int start_block = 0;
+#if ANDROID_TILE_BASED_DECODE
+    if (cinfo->tile_decode) {
+      width_in_blocks = jmin(width_in_blocks,
+        (cinfo->coef->MCU_column_right_boundary -
+         cinfo->coef->MCU_column_left_boundary) *
+         cinfo->max_h_samp_factor /
+         compptr->h_samp_factor);
+      start_block = coef->pub.MCU_columns_to_skip *
+        cinfo->max_h_samp_factor / compptr->h_samp_factor;
+    }
+#endif
     /* Loop over all DCT blocks to be processed. */
     for (block_row = 0; block_row < block_rows; block_row++) {
       buffer_ptr = buffer[block_row];
-      output_col = 0;
-      for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
+      output_col = start_block * compptr->DCT_scaled_size;
+      buffer_ptr += start_block;
+      for (block_num = start_block; block_num < width_in_blocks; block_num++) {
 	(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
 			output_ptr, output_col);
 	buffer_ptr++;
@@ -907,6 +925,7 @@
   coef->pub.start_output_pass = start_output_pass;
   coef->pub.column_left_boundary = 0;
   coef->pub.column_right_boundary = 0;
+  coef->pub.MCU_columns_to_skip = 0;
 #ifdef BLOCK_SMOOTHING_SUPPORTED
   coef->coef_bits_latch = NULL;
 #endif
diff --git a/jdhuff.c b/jdhuff.c
index 9164d17..0d704a5 100644
--- a/jdhuff.c
+++ b/jdhuff.c
@@ -519,6 +519,7 @@
   int blkn, i;
 
   cinfo->restart_interval = 0;
+  cinfo->unread_marker = 0;
 
   unsigned int byte_offset = bitstream_offset >> LOG_TWO_BIT_BUF_SIZE;
   unsigned int bit_in_bit_buffer =
diff --git a/jdmaster.c b/jdmaster.c
index e44d662..e3da758 100644
--- a/jdmaster.c
+++ b/jdmaster.c
@@ -103,9 +103,12 @@
 #endif
 
   /* Prevent application from calling me at wrong times */
-  // FIXME
-  //if (cinfo->global_state != DSTATE_READY)
-  //  ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+#if ANDROID_TILE_BASED_DECODE
+  // Tile based decoding may call this function several times.
+  if (!cinfo->tile_decode)
+#endif
+    if (cinfo->global_state != DSTATE_READY)
+      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
 
 #ifdef IDCT_SCALING_SUPPORTED
 
diff --git a/jpegint.h b/jpegint.h
index fd6d8bb..3b5511e 100644
--- a/jpegint.h
+++ b/jpegint.h
@@ -177,10 +177,20 @@
 				 JSAMPIMAGE output_buf));
   /* Pointer to array of coefficient virtual arrays, or NULL if none */
   jvirt_barray_ptr *coef_arrays;
+
+  /* column number of the first and last tile, respectively */
   int column_left_boundary;
   int column_right_boundary;
+
+  /* column number of the first and last MCU, respectively */
   int MCU_column_left_boundary;
   int MCU_column_right_boundary;
+
+  /* the number of MCU columns to skip from the indexed MCU, iM,
+   * to the requested MCU boundary, rM, where iM is the MCU that we sample
+   * into our index and is the nearest one to the left of rM.
+   */
+  int MCU_columns_to_skip;
 };
 
 /* Decompression postprocessing (color quantization buffer control) */
diff --git a/jpeglib.h b/jpeglib.h
index 1dccc87..83bed4a 100644
--- a/jpeglib.h
+++ b/jpeglib.h
@@ -1043,9 +1043,7 @@
 					    JDIMENSION max_lines));
 EXTERN(JDIMENSION) jpeg_read_tile_scanline JPP((j_decompress_ptr cinfo,
                         huffman_index *index,
-                        JSAMPARRAY scanlines,
-		                int start_x, int start_y,
-                        int width, int height));
+                        JSAMPARRAY scanlines));
 EXTERN(void) jpeg_init_read_tile_scanline JPP((j_decompress_ptr cinfo,
                         huffman_index *index,
 		                int *start_x, int *start_y,