• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkImageDecoder_PVJPEG_Factory(SkStream * stream)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:
AutoPVDelete(PVJpgDecoderInterface * codec)34     AutoPVDelete(PVJpgDecoderInterface* codec) : fCodec(codec) {}
~AutoPVDelete()35     ~AutoPVDelete() {
36         fCodec->Reset();
37         PVJpgDecoderFactory::DeletePVJpgDecoder(fCodec);
38     }
39 private:
40     PVJpgDecoderInterface* fCodec;
41 };
42 
43 class MyObserver : public MPVJpegDecObserver {
44 public:
MyObserver()45     MyObserver() : fCount(0) {}
~MyObserver()46     ~MyObserver() {
47         if (fCount != 0) {
48             SkDebugf("--- pvjpeg left %d allocations\n", fCount);
49         }
50     }
51 
allocateBuffer(uint8 * & buffer,int32 buffersize)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 
deallocateBuffer(uint8 * buffer)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 
check_status(TPvJpgDecStatus status)69 static void check_status(TPvJpgDecStatus status) {
70     if (TPVJPGDEC_SUCCESS != status) {
71         SkDEBUGF(("--- pvjpeg status %d\n", status));
72     }
73 }
74 
getFrame(PVJpgDecoderInterface * codec,SkBitmap * bitmap,SkBitmap::Config prefConfig,SkImageDecoder::Mode mode)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:
OsclCleanupper()128     OsclCleanupper() {
129         OsclBase::Init();
130         OsclErrorTrap::Init();
131         OsclMem::Init();
132     }
~OsclCleanupper()133     ~OsclCleanupper() {
134         OsclMem::Cleanup();
135         OsclErrorTrap::Cleanup();
136         OsclBase::Cleanup();
137     }
138 };
139 
onDecode(SkStream * stream,SkBitmap * decodedBitmap,SkBitmap::Config prefConfig,Mode mode)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