acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
MjpegClass.h (4763B)
1 /******************************************************************************* 2 * JPEGDEC Wrapper Class 3 * 4 * Dependent libraries: 5 * JPEGDEC: https://github.com/bitbank2/JPEGDEC.git 6 ******************************************************************************/ 7 #ifndef _MJPEGCLASS_H_ 8 #define _MJPEGCLASS_H_ 9 10 #define READ_BUFFER_SIZE 1024 11 #define MAXOUTPUTSIZE (MAX_BUFFERED_PIXELS / 16 / 16) 12 13 /* Wio Terminal */ 14 #if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS) 15 #include <Seeed_FS.h> 16 #elif defined(ESP32) || defined(ESP8266) 17 #include <FS.h> 18 #else 19 #include <SD.h> 20 #endif 21 22 #include <JPEGDEC.h> 23 24 class MjpegClass 25 { 26 public: 27 bool setup( 28 Stream *input, uint8_t *mjpeg_buf, JPEG_DRAW_CALLBACK *pfnDraw, bool useBigEndian, 29 int x, int y, int widthLimit, int heightLimit) 30 { 31 _input = input; 32 _mjpeg_buf = mjpeg_buf; 33 _pfnDraw = pfnDraw; 34 _useBigEndian = useBigEndian; 35 _x = x; 36 _y = y; 37 _widthLimit = widthLimit; 38 _heightLimit = heightLimit; 39 _inputindex = 0; 40 41 if (!_read_buf) 42 { 43 _read_buf = (uint8_t *)malloc(READ_BUFFER_SIZE); 44 } 45 46 return true; 47 } 48 49 bool readMjpegBuf() 50 { 51 if (_inputindex == 0) 52 { 53 _buf_read = _input->readBytes(_read_buf, READ_BUFFER_SIZE); 54 _inputindex += _buf_read; 55 } 56 _mjpeg_buf_offset = 0; 57 int i = 0; 58 bool found_FFD8 = false; 59 while ((_buf_read > 0) && (!found_FFD8)) 60 { 61 i = 0; 62 while ((i < _buf_read) && (!found_FFD8)) 63 { 64 if ((_read_buf[i] == 0xFF) && (_read_buf[i + 1] == 0xD8)) // JPEG header 65 { 66 // Serial.printf("Found FFD8 at: %d.\n", i); 67 found_FFD8 = true; 68 } 69 ++i; 70 } 71 if (found_FFD8) 72 { 73 --i; 74 } 75 else 76 { 77 _buf_read = _input->readBytes(_read_buf, READ_BUFFER_SIZE); 78 } 79 } 80 uint8_t *_p = _read_buf + i; 81 _buf_read -= i; 82 bool found_FFD9 = false; 83 if (_buf_read > 0) 84 { 85 i = 3; 86 while ((_buf_read > 0) && (!found_FFD9)) 87 { 88 if ((_mjpeg_buf_offset > 0) && (_mjpeg_buf[_mjpeg_buf_offset - 1] == 0xFF) && (_p[0] == 0xD9)) // JPEG trailer 89 { 90 // Serial.printf("Found FFD9 at: %d.\n", i); 91 found_FFD9 = true; 92 } 93 else 94 { 95 while ((i < _buf_read) && (!found_FFD9)) 96 { 97 if ((_p[i] == 0xFF) && (_p[i + 1] == 0xD9)) // JPEG trailer 98 { 99 found_FFD9 = true; 100 ++i; 101 } 102 ++i; 103 } 104 } 105 106 // Serial.printf("i: %d\n", i); 107 memcpy(_mjpeg_buf + _mjpeg_buf_offset, _p, i); 108 _mjpeg_buf_offset += i; 109 size_t o = _buf_read - i; 110 if (o > 0) 111 { 112 // Serial.printf("o: %d\n", o); 113 memcpy(_read_buf, _p + i, o); 114 _buf_read = _input->readBytes(_read_buf + o, READ_BUFFER_SIZE - o); 115 _p = _read_buf; 116 _inputindex += _buf_read; 117 _buf_read += o; 118 // Serial.printf("_buf_read: %d\n", _buf_read); 119 } 120 else 121 { 122 _buf_read = _input->readBytes(_read_buf, READ_BUFFER_SIZE); 123 _p = _read_buf; 124 _inputindex += _buf_read; 125 } 126 i = 0; 127 } 128 if (found_FFD9) 129 { 130 return true; 131 } 132 } 133 134 return false; 135 } 136 137 bool drawJpg() 138 { 139 _remain = _mjpeg_buf_offset; 140 _jpeg.openRAM(_mjpeg_buf, _remain, _pfnDraw); 141 if (_scale == -1) 142 { 143 // scale to fit height 144 int iMaxMCUs; 145 int w = _jpeg.getWidth(); 146 int h = _jpeg.getHeight(); 147 float ratio = (float)h / _heightLimit; 148 if (ratio <= 1) 149 { 150 _scale = 0; 151 iMaxMCUs = _widthLimit / 16; 152 } 153 else if (ratio <= 2) 154 { 155 _scale = JPEG_SCALE_HALF; 156 iMaxMCUs = _widthLimit / 8; 157 w /= 2; 158 h /= 2; 159 } 160 else if (ratio <= 4) 161 { 162 _scale = JPEG_SCALE_QUARTER; 163 iMaxMCUs = _widthLimit / 4; 164 w /= 4; 165 h /= 4; 166 } 167 else 168 { 169 _scale = JPEG_SCALE_EIGHTH; 170 iMaxMCUs = _widthLimit / 2; 171 w /= 8; 172 h /= 8; 173 } 174 _jpeg.setMaxOutputSize(iMaxMCUs); 175 _x = (w > _widthLimit) ? 0 : ((_widthLimit - w) / 2); 176 _y = (_heightLimit - h) / 2; 177 } 178 if (_useBigEndian) 179 { 180 _jpeg.setPixelType(RGB565_BIG_ENDIAN); 181 } 182 _jpeg.decode(_x, _y, _scale); 183 _jpeg.close(); 184 185 return true; 186 } 187 188 private: 189 Stream *_input; 190 uint8_t *_mjpeg_buf; 191 JPEG_DRAW_CALLBACK *_pfnDraw; 192 bool _useBigEndian; 193 int _x; 194 int _y; 195 int _widthLimit; 196 int _heightLimit; 197 198 uint8_t *_read_buf; 199 int32_t _mjpeg_buf_offset = 0; 200 201 JPEGDEC _jpeg; 202 int _scale = -1; 203 204 int32_t _inputindex = 0; 205 int32_t _buf_read; 206 int32_t _remain = 0; 207 }; 208 209 #endif // _MJPEGCLASS_H_