Home | History | Annotate | Download | only in images
      1 #include "SkImageDecoder.h"
      2 #include "SkColor.h"
      3 #include "SkColorPriv.h"
      4 #include "SkDither.h"
      5 #include "SkMath.h"
      6 #include "SkStream.h"
      7 #include "SkTemplates.h"
      8 #include "SkUtils.h"
      9 
     10 extern void ValidateHeap();
     11 
     12 class SkPVJPEGImageDecoder : public SkImageDecoder {
     13 protected:
     14     virtual bool onDecode(SkStream* stream, SkBitmap* bm,
     15                           SkBitmap::Config pref, Mode);
     16 
     17 private:
     18     enum {
     19         STORAGE_SIZE = 8 * 1024
     20     };
     21     char    fStorage[STORAGE_SIZE];
     22 };
     23 
     24 SkImageDecoder* SkImageDecoder_PVJPEG_Factory(SkStream* stream)
     25 {
     26     return SkNEW(SkPVJPEGImageDecoder);
     27 }
     28 
     29 #include "pvjpgdecoderinterface.h"
     30 #include "pvjpgdecoder_factory.h"
     31 
     32 class AutoPVDelete {
     33 public:
     34     AutoPVDelete(PVJpgDecoderInterface* codec) : fCodec(codec) {}
     35     ~AutoPVDelete() {
     36         fCodec->Reset();
     37         PVJpgDecoderFactory::DeletePVJpgDecoder(fCodec);
     38     }
     39 private:
     40     PVJpgDecoderInterface* fCodec;
     41 };
     42 
     43 class MyObserver : public MPVJpegDecObserver {
     44 public:
     45     MyObserver() : fCount(0) {}
     46     ~MyObserver() {
     47         if (fCount != 0) {
     48             SkDebugf("--- pvjpeg left %d allocations\n", fCount);
     49         }
     50     }
     51 
     52 	virtual void allocateBuffer(uint8* &buffer, int32 buffersize) {
     53         ++fCount;
     54         // we double the allocation to work around bug when height is odd
     55         buffer = (uint8*)sk_malloc_throw(buffersize << 1);
     56         SkDebugf("---  pvjpeg alloc [%d] %d addr=%p\n", fCount, buffersize, buffer);
     57     }
     58 
     59 	virtual void deallocateBuffer(uint8 *buffer) {
     60         SkDebugf("--- pvjpeg free [%d] addr=%p\n", fCount, buffer);
     61         --fCount;
     62         sk_free(buffer);
     63     }
     64 
     65 private:
     66     int fCount;
     67 };
     68 
     69 static void check_status(TPvJpgDecStatus status) {
     70     if (TPVJPGDEC_SUCCESS != status) {
     71         SkDEBUGF(("--- pvjpeg status %d\n", status));
     72     }
     73 }
     74 
     75 static bool getFrame(PVJpgDecoderInterface* codec, SkBitmap* bitmap,
     76                      SkBitmap::Config prefConfig, SkImageDecoder::Mode mode) {
     77     TPvJpgDecInfo info;
     78     TPvJpgDecStatus status = codec->GetInfo(&info);
     79     if (status != TPVJPGDEC_SUCCESS)
     80         return false;
     81 
     82     int width = info.iWidth[0];
     83     int height = info.iHeight[0];
     84 
     85     bitmap->setConfig(SkBitmap::kRGB_565_Config, width, height);
     86     bitmap->setIsOpaque(true);
     87 
     88     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
     89         return true;
     90     }
     91 
     92     SkASSERT(info.iNumComponent == 3);
     93 
     94     TPvJpgDecOutputFmt  format;
     95     format.iColorFormat = TPV_COLORFMT_RGB16;
     96     format.iCropped.topLeftX = 0;
     97     format.iCropped.topLeftY = 0;
     98     format.iCropped.bottomRightX = width - 1;
     99     format.iCropped.bottomRightY = height - 1;
    100     format.iOutputPitch = bitmap->rowBytes() >> 1;
    101     status = codec->SetOutput(&format);
    102     if (status != TPVJPGDEC_SUCCESS) {
    103         SkDebugf("--- PV SetOutput failed %d\n", status);
    104         return false;
    105     }
    106 
    107     TPvJpgDecFrame frame;
    108     uint8*         ptrs[3];
    109     int32          widths[3], heights[3];
    110     sk_bzero(ptrs, sizeof(ptrs));
    111     frame.ptr = ptrs;
    112     frame.iWidth = widths;
    113     frame.iHeight = heights;
    114 
    115     status = codec->GetFrame(&frame);
    116     if (status != TPVJPGDEC_SUCCESS) {
    117         SkDebugf("--- PV GetFrame failed %d\n", status);
    118         return false;
    119     }
    120 
    121     bitmap->allocPixels();
    122     memcpy(bitmap->getPixels(), ptrs[0], bitmap->getSize());
    123     return true;
    124 }
    125 
    126 class OsclCleanupper {
    127 public:
    128     OsclCleanupper() {
    129         OsclBase::Init();
    130         OsclErrorTrap::Init();
    131         OsclMem::Init();
    132     }
    133     ~OsclCleanupper() {
    134         OsclMem::Cleanup();
    135         OsclErrorTrap::Cleanup();
    136         OsclBase::Cleanup();
    137     }
    138 };
    139 
    140 bool SkPVJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
    141                                     SkBitmap::Config prefConfig, Mode mode)
    142 {
    143     // do I need this guy?
    144     OsclCleanupper oc;
    145 
    146     PVJpgDecoderInterface*  codec = PVJpgDecoderFactory::CreatePVJpgDecoder();
    147     TPvJpgDecStatus         status = codec->Init();
    148     check_status(status);
    149 
    150     MyObserver      observer;   // must create before autopvdelete
    151     AutoPVDelete    ad(codec);
    152 
    153     status = codec->SetObserver(&observer);
    154     check_status(status);
    155 
    156     char*   storage = fStorage;
    157     int32   bytesInStorage = 0;
    158     for (;;)
    159     {
    160         int32 bytesRead = stream->read(storage + bytesInStorage,
    161                                        STORAGE_SIZE - bytesInStorage);
    162         if (bytesRead <= 0) {
    163             SkDEBUGF(("SkPVJPEGImageDecoder: stream read returned %d\n", bytesRead));
    164             return false;
    165         }
    166 
    167         // update bytesInStorage to account for the read()
    168         bytesInStorage += bytesRead;
    169         SkASSERT(bytesInStorage <= STORAGE_SIZE);
    170 
    171         // now call Decode to eat some of the bytes
    172         int32 consumed = bytesInStorage;
    173         status = codec->Decode((uint8*)storage, &consumed);
    174 
    175         SkASSERT(bytesInStorage >= consumed);
    176         bytesInStorage -= consumed;
    177         // now bytesInStorage is the remaining unread bytes
    178         if (bytesInStorage > 0) { // slide the leftovers to the beginning
    179             SkASSERT(storage == fStorage);
    180             SkASSERT(consumed >= 0 && bytesInStorage >= 0);
    181             SkASSERT((size_t)(consumed + bytesInStorage) <= sizeof(fStorage));
    182             SkASSERT(sizeof(fStorage) == STORAGE_SIZE);
    183        //     SkDebugf("-- memmov srcOffset=%d, numBytes=%d\n", consumed, bytesInStorage);
    184             memmove(storage, storage + consumed, bytesInStorage);
    185         }
    186 
    187         switch (status) {
    188         case TPVJPGDEC_SUCCESS:
    189             SkDEBUGF(("SkPVJPEGImageDecoder::Decode returned success?\n");)
    190             return false;
    191         case TPVJPGDEC_FRAME_READY:
    192         case TPVJPGDEC_DONE:
    193             return getFrame(codec, decodedBitmap, prefConfig, mode);
    194         case TPVJPGDEC_FAIL:
    195         case TPVJPGDEC_INVALID_MEMORY:
    196         case TPVJPGDEC_INVALID_PARAMS:
    197         case TPVJPGDEC_NO_IMAGE_DATA:
    198             SkDEBUGF(("SkPVJPEGImageDecoder: failed to decode err=%d\n", status);)
    199             return false;
    200         case TPVJPGDEC_WAITING_FOR_INPUT:
    201             break;  // loop around and eat more from the stream
    202         }
    203     }
    204     return false;
    205 }
    206 
    207