Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkCodecPriv.h"
      9 #include "SkJpegUtility_codec.h"
     10 
     11 /*
     12  * Initialize the source manager
     13  */
     14 static void sk_init_source(j_decompress_ptr dinfo) {
     15     skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src;
     16     src->next_input_byte = (const JOCTET*) src->fBuffer;
     17     src->bytes_in_buffer = 0;
     18 }
     19 
     20 /*
     21  * Fill the input buffer from the stream
     22  */
     23 static boolean sk_fill_input_buffer(j_decompress_ptr dinfo) {
     24     skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src;
     25     size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
     26 
     27     // libjpeg is still happy with a less than full read, as long as the result is non-zero
     28     if (bytes == 0) {
     29         return false;
     30     }
     31 
     32     src->next_input_byte = (const JOCTET*) src->fBuffer;
     33     src->bytes_in_buffer = bytes;
     34     return true;
     35 }
     36 
     37 /*
     38  * Skip a certain number of bytes in the stream
     39  */
     40 static void sk_skip_input_data(j_decompress_ptr dinfo, long numBytes) {
     41     skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src;
     42     size_t bytes = (size_t) numBytes;
     43 
     44     if (bytes > src->bytes_in_buffer) {
     45         size_t bytesToSkip = bytes - src->bytes_in_buffer;
     46         if (bytesToSkip != src->fStream->skip(bytesToSkip)) {
     47             SkCodecPrintf("Failure to skip.\n");
     48             dinfo->err->error_exit((j_common_ptr) dinfo);
     49             return;
     50         }
     51 
     52         src->next_input_byte = (const JOCTET*) src->fBuffer;
     53         src->bytes_in_buffer = 0;
     54     } else {
     55         src->next_input_byte += numBytes;
     56         src->bytes_in_buffer -= numBytes;
     57     }
     58 }
     59 
     60 /*
     61  * We do not need to do anything to terminate our stream
     62  */
     63 static void sk_term_source(j_decompress_ptr dinfo)
     64 {
     65     // The current implementation of SkJpegCodec does not call
     66     // jpeg_finish_decompress(), so this function is never called.
     67     // If we want to modify this function to do something, we also
     68     // need to modify SkJpegCodec to call jpeg_finish_decompress().
     69 }
     70 
     71 /*
     72  * Constructor for the source manager that we provide to libjpeg
     73  * We provide skia implementations of all of the stream processing functions required by libjpeg
     74  */
     75 skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream)
     76     : fStream(stream)
     77 {
     78     init_source = sk_init_source;
     79     fill_input_buffer = sk_fill_input_buffer;
     80     skip_input_data = sk_skip_input_data;
     81     resync_to_restart = jpeg_resync_to_restart;
     82     term_source = sk_term_source;
     83 }
     84 
     85 /*
     86  * Call longjmp to continue execution on an error
     87  */
     88 void skjpeg_err_exit(j_common_ptr dinfo) {
     89     // Simply return to Skia client code
     90     // JpegDecoderMgr will take care of freeing memory
     91     skjpeg_error_mgr* error = (skjpeg_error_mgr*) dinfo->err;
     92     (*error->output_message) (dinfo);
     93     longjmp(error->fJmpBuf, 1);
     94 }
     95