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