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_