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

ImgViewerMjpeg.ino (9746B)

      1 /*******************************************************************************
      2  * Motion JPEG Image Viewer
      3  * This is a simple Motion JPEG image viewer example
      4  * Image Source: https://www.pexels.com/video/earth-rotating-video-856356/
      5  * cropped: x: 598 y: 178 width: 720 height: 720 resized: 240x240
      6  * ffmpeg -i "Pexels Videos 3931.mp4" -ss 0 -t 20.4s -vf "reverse,setpts=0.5*PTS,fps=10,vflip,hflip,rotate=90,crop=720:720:178:598,scale=240:240:flags=lanczos" -pix_fmt yuv420p -q:v 9 earth.mjpeg
      7  *
      8  * Dependent libraries:
      9  * JPEGDEC: https://github.com/bitbank2/JPEGDEC.git
     10  *
     11  * Setup steps:
     12  * 1. Change your LCD parameters in Arduino_GFX setting
     13  * 2. Upload Motion JPEG file
     14  *   FFat (ESP32):
     15  *     upload FFat (FatFS) data with ESP32 Sketch Data Upload:
     16  *     ESP32: https://github.com/lorol/arduino-esp32fs-plugin
     17  *   LittleFS (ESP32 / ESP8266 / Pico):
     18  *     upload LittleFS data with ESP8266 LittleFS Data Upload:
     19  *     ESP32: https://github.com/lorol/arduino-esp32fs-plugin
     20  *     ESP8266: https://github.com/earlephilhower/arduino-esp8266littlefs-plugin
     21  *     Pico: https://github.com/earlephilhower/arduino-pico-littlefs-plugin.git
     22  *   SPIFFS (ESP32):
     23  *     upload SPIFFS data with ESP32 Sketch Data Upload:
     24  *     ESP32: https://github.com/lorol/arduino-esp32fs-plugin
     25  *   SD:
     26  *     Most Arduino system built-in support SD file system.
     27  *     Wio Terminal require extra dependant Libraries:
     28  *     - Seeed_Arduino_FS: https://github.com/Seeed-Studio/Seeed_Arduino_FS.git
     29  *     - Seeed_Arduino_SFUD: https://github.com/Seeed-Studio/Seeed_Arduino_SFUD.git
     30  ******************************************************************************/
     31 #define MJPEG_FILENAME "/earth.mjpeg"
     32 #define MJPEG_BUFFER_SIZE (240 * 240 * 2 / 10) // memory for a single JPEG frame
     33 // #define MJPEG_FILENAME "/earth128.mjpeg"
     34 // #define MJPEG_BUFFER_SIZE (128 * 128 * 2 / 10) // memory for a single JPEG frame
     35 
     36 /*******************************************************************************
     37  * Start of Arduino_GFX setting
     38  *
     39  * Arduino_GFX try to find the settings depends on selected board in Arduino IDE
     40  * Or you can define the display dev kit not in the board list
     41  * Defalult pin list for non display dev kit:
     42  * Arduino Nano, Micro and more: CS:  9, DC:  8, RST:  7, BL:  6, SCK: 13, MOSI: 11, MISO: 12
     43  * ESP32 various dev board     : CS:  5, DC: 27, RST: 33, BL: 22, SCK: 18, MOSI: 23, MISO: nil
     44  * ESP32-C3 various dev board  : CS:  7, DC:  2, RST:  1, BL:  3, SCK:  4, MOSI:  6, MISO: nil
     45  * ESP32-S2 various dev board  : CS: 34, DC: 38, RST: 33, BL: 21, SCK: 36, MOSI: 35, MISO: nil
     46  * ESP32-S3 various dev board  : CS: 40, DC: 41, RST: 42, BL: 48, SCK: 36, MOSI: 35, MISO: nil
     47  * ESP8266 various dev board   : CS: 15, DC:  4, RST:  2, BL:  5, SCK: 14, MOSI: 13, MISO: 12
     48  * Raspberry Pi Pico dev board : CS: 17, DC: 27, RST: 26, BL: 28, SCK: 18, MOSI: 19, MISO: 16
     49  * RTL8720 BW16 old patch core : CS: 18, DC: 17, RST:  2, BL: 23, SCK: 19, MOSI: 21, MISO: 20
     50  * RTL8720_BW16 Official core  : CS:  9, DC:  8, RST:  6, BL:  3, SCK: 10, MOSI: 12, MISO: 11
     51  * RTL8722 dev board           : CS: 18, DC: 17, RST: 22, BL: 23, SCK: 13, MOSI: 11, MISO: 12
     52  * RTL8722_mini dev board      : CS: 12, DC: 14, RST: 15, BL: 13, SCK: 11, MOSI:  9, MISO: 10
     53  * Seeeduino XIAO dev board    : CS:  3, DC:  2, RST:  1, BL:  0, SCK:  8, MOSI: 10, MISO:  9
     54  * Teensy 4.1 dev board        : CS: 39, DC: 41, RST: 40, BL: 22, SCK: 13, MOSI: 11, MISO: 12
     55  ******************************************************************************/
     56 #include <Arduino_GFX_Library.h>
     57 
     58 #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
     59 
     60 /* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
     61 #if defined(DISPLAY_DEV_KIT)
     62 Arduino_GFX *gfx = create_default_Arduino_GFX();
     63 #else /* !defined(DISPLAY_DEV_KIT) */
     64 
     65 /* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
     66 Arduino_DataBus *bus = create_default_Arduino_DataBus();
     67 
     68 /* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
     69 Arduino_GFX *gfx = new Arduino_ILI9341(bus, DF_GFX_RST, 3 /* rotation */, false /* IPS */);
     70 
     71 #endif /* !defined(DISPLAY_DEV_KIT) */
     72 /*******************************************************************************
     73  * End of Arduino_GFX setting
     74  ******************************************************************************/
     75 
     76 /* Wio Terminal */
     77 #if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
     78 #include <Seeed_FS.h>
     79 #include <SD/Seeed_SD.h>
     80 #elif defined(TARGET_RP2040)
     81 #include <LittleFS.h>
     82 #include <SD.h>
     83 #elif defined(ESP32)
     84 #include <FFat.h>
     85 #include <LittleFS.h>
     86 #include <SPIFFS.h>
     87 #include <SD.h>
     88 #include <SD_MMC.h>
     89 #elif defined(ESP8266)
     90 #include <LittleFS.h>
     91 #include <SD.h>
     92 #else
     93 #include <SD.h>
     94 #endif
     95 
     96 #include "MjpegClass.h"
     97 static MjpegClass mjpeg;
     98 
     99 /* variables */
    100 static int total_frames = 0;
    101 static unsigned long total_read_video = 0;
    102 static unsigned long total_decode_video = 0;
    103 static unsigned long total_show_video = 0;
    104 static unsigned long start_ms, curr_ms;
    105 
    106 // pixel drawing callback
    107 static int jpegDrawCallback(JPEGDRAW *pDraw)
    108 {
    109   // Serial.printf("Draw pos = %d,%d. size = %d x %d\n", pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight);
    110   unsigned long start = millis();
    111   gfx->draw16bitBeRGBBitmap(pDraw->x, pDraw->y, pDraw->pPixels, pDraw->iWidth, pDraw->iHeight);
    112   total_show_video += millis() - start;
    113   return 1;
    114 }
    115 
    116 void setup()
    117 {
    118   Serial.begin(115200);
    119   // Serial.setDebugOutput(true);
    120   // while(!Serial);
    121   Serial.println("MJPEG Image Viewer");
    122 
    123 #ifdef GFX_EXTRA_PRE_INIT
    124   GFX_EXTRA_PRE_INIT();
    125 #endif
    126 
    127   // Init Display
    128   gfx->begin();
    129   gfx->fillScreen(BLACK);
    130 
    131 #ifdef GFX_BL
    132   pinMode(GFX_BL, OUTPUT);
    133   digitalWrite(GFX_BL, HIGH);
    134 #endif
    135 
    136 /* Wio Terminal */
    137 #if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
    138   // Init SPIFLASH
    139   if (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI, 4000000UL))
    140 #elif defined(TARGET_RP2040)
    141   if (!LittleFS.begin())
    142   // if (!SD.begin(SS))
    143 #elif defined(ESP32)
    144   // if (!FFat.begin())
    145   if (!LittleFS.begin())
    146   // if (!SPIFFS.begin())
    147   // if (!SD.begin(SS))
    148   // pinMode(10 /* CS */, OUTPUT);
    149   // digitalWrite(10 /* CS */, HIGH);
    150   // SD_MMC.setPins(12 /* CLK */, 11 /* CMD/MOSI */, 13 /* D0/MISO */);
    151   // if (!SD_MMC.begin("/root", true))
    152 #elif defined(ESP8266)
    153   if (!LittleFS.begin())
    154   // if (!SD.begin(SS))
    155 #else
    156   if (!SD.begin())
    157 #endif
    158   {
    159     Serial.println(F("ERROR: File System Mount Failed!"));
    160     gfx->println(F("ERROR: File System Mount Failed!"));
    161   }
    162   else
    163   {
    164 #if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
    165     File mjpegFile = SD.open(MJPEG_FILENAME, "r");
    166 #elif defined(TARGET_RP2040)
    167     File mjpegFile = LittleFS.open(MJPEG_FILENAME, "r");
    168     // File mjpegFile = SD.open(MJPEG_FILENAME, "r");
    169 #elif defined(ESP32)
    170     // File mjpegFile = FFat.open(MJPEG_FILENAME, "r");
    171     File mjpegFile = LittleFS.open(MJPEG_FILENAME, "r");
    172     // File mjpegFile = SPIFFS.open(MJPEG_FILENAME, "r");
    173     // File mjpegFile = SD.open(MJPEG_FILENAME, "r");
    174     // File mjpegFile = SD_MMC.open(MJPEG_FILENAME, "r");
    175 #elif defined(ESP8266)
    176     File mjpegFile = LittleFS.open(MJPEG_FILENAME, "r");
    177     // File mjpegFile = SD.open(MJPEG_FILENAME, "r");
    178 #else
    179     File mjpegFile = SD.open(MJPEG_FILENAME, FILE_READ);
    180 #endif
    181 
    182     if (!mjpegFile || mjpegFile.isDirectory())
    183     {
    184       Serial.println(F("ERROR: Failed to open " MJPEG_FILENAME " file for reading"));
    185       gfx->println(F("ERROR: Failed to open " MJPEG_FILENAME " file for reading"));
    186     }
    187     else
    188     {
    189       uint8_t *mjpeg_buf = (uint8_t *)malloc(MJPEG_BUFFER_SIZE);
    190       if (!mjpeg_buf)
    191       {
    192         Serial.println(F("mjpeg_buf malloc failed!"));
    193       }
    194       else
    195       {
    196         Serial.println(F("MJPEG start"));
    197 
    198         start_ms = millis();
    199         curr_ms = millis();
    200         mjpeg.setup(
    201             &mjpegFile, mjpeg_buf, jpegDrawCallback, true /* useBigEndian */,
    202             0 /* x */, 0 /* y */, gfx->width() /* widthLimit */, gfx->height() /* heightLimit */);
    203 
    204         while (mjpegFile.available() && mjpeg.readMjpegBuf())
    205         {
    206           // Read video
    207           total_read_video += millis() - curr_ms;
    208           curr_ms = millis();
    209 
    210           // Play video
    211           mjpeg.drawJpg();
    212           total_decode_video += millis() - curr_ms;
    213 
    214           curr_ms = millis();
    215           total_frames++;
    216         }
    217         int time_used = millis() - start_ms;
    218         Serial.println(F("MJPEG end"));
    219         mjpegFile.close();
    220         float fps = 1000.0 * total_frames / time_used;
    221         total_decode_video -= total_show_video;
    222         Serial.printf("Total frames: %d\n", total_frames);
    223         Serial.printf("Time used: %d ms\n", time_used);
    224         Serial.printf("Average FPS: %0.1f\n", fps);
    225         Serial.printf("Read MJPEG: %lu ms (%0.1f %%)\n", total_read_video, 100.0 * total_read_video / time_used);
    226         Serial.printf("Decode video: %lu ms (%0.1f %%)\n", total_decode_video, 100.0 * total_decode_video / time_used);
    227         Serial.printf("Show video: %lu ms (%0.1f %%)\n", total_show_video, 100.0 * total_show_video / time_used);
    228 
    229         gfx->setCursor(0, 0);
    230         gfx->printf("Total frames: %d\n", total_frames);
    231         gfx->printf("Time used: %d ms\n", time_used);
    232         gfx->printf("Average FPS: %0.1f\n", fps);
    233         gfx->printf("Read MJPEG: %lu ms (%0.1f %%)\n", total_read_video, 100.0 * total_read_video / time_used);
    234         gfx->printf("Decode video: %lu ms (%0.1f %%)\n", total_decode_video, 100.0 * total_decode_video / time_used);
    235         gfx->printf("Show video: %lu ms (%0.1f %%)\n", total_show_video, 100.0 * total_show_video / time_used);
    236       }
    237     }
    238   }
    239 }
    240 
    241 void loop()
    242 {
    243 }