prenticedavid / AnimatedGIFs_SD

Display GIFs from Flash, SD or SPIFFS
64 stars 14 forks source link

Framerate expectations? #2

Open t0mg opened 4 years ago

t0mg commented 4 years ago

Hi there. After some fiddling I got this to work on this ESP32 board with 1.44" TFT (128x128) . It's using TFT_eSPI library. For some reason I got divides by zero in the loop where you compute some debug data, and also none of the gifs included in the .h files are displayed. However it works with SPIFFS which is good enough for now.

The provided sample bottom_128x128x17.gif decodes at ~38ms per frame, about 44% speed.

I created another 128x128 gif which I optimized with this software. It's based on a video so much heavier, about 680Kb. I also tried another one that weighted about 1.2Mb. Both decode at about 140ms per frame.

So my question is, is this about what to expect on this kind of hardware, or is there something wrong ?

Thanks !

prenticedavid commented 4 years ago

GIF animations vary.

  1. draw a complete frame i.e. every pixel.

  2. next frame draws a minimal rectangle i.e. where pixels have changed.

  3. when drawing the changed frame there are different strategies. either draw every pixel in the (smaller) rectangle. or skip unchanged pixels. draw changed pixels.

  4. skipping several pixels is efficient. skipping an individual pixel is expensive on a ST7735.

You appear to have been a GitHub member for some time. I have not worked on this project for months. If you want me to help, you should provide proper information. e.g. post link to your original GIF, optimized GIF. If you Fork the project, we can see each other's software.

I am wary of websites with big GREEN buttons. Can you verify that this site is safe and which "download button" you used (and is safe)

David.

t0mg commented 4 years ago

Hey David, thanks for your reply.

The software I mentioned was merely for information and context, there is really no need for you to download it (my antivirus thinks it's safe though). Sorry if that came out wrong but I didn't mean to ask you to help me optimize a random gif :) I was only really asking what framerate I should be expecting on this hardware with the provided bottom_128x128x17.gif as it felt somewhat low but I literally don't know what I'm talking about. Since then I updated TFT_eSPI to 2.0 from github (don't know why Arduino IDE only gets up to 1.4) and the speed got much better! So decoding wasn't actually the bottleneck here.

I also got the SD card reader to work on my board, so I'm almost all set!

However, I'm still unable to get any gif to display from anything else than SPIFFS. On SD and from flash I'm only getting a white screen and I could use some guidance on how to debug it. Here are some serial logs I'm getting in each of the three modes :

SPIFFS: both test gifs get displayed correctly - not sure why there is a 0 frames count on test2.gif

AnimatedGIFs_SD
1:/test1.gif    size:711166
2:/test2.gif    size:173301
Animated GIF files Found: 2
Init complete
[0 frames = 0ms] actual: 1196ms speed: 0% plot: 0
Pathname: /test1.gif
Logical Screen [LZW=5 128x128 P:0xF4 B:27 A:0 F:10ms] frames:0 pass=1
[142 frames = 1420ms] actual: 8628ms speed: 16% plot: 2319257
Pathname: /test2.gif
Logical Screen [LZW=6 117x128 P:0xF5 B:14 A:0 F:70ms] frames:0 pass=1
[0 frames = 7350ms] actual: 10143ms speed: 72% plot: 1344544

1Gb FAT SD: white screen but decoding seems to work, the timing seems correct when compared with SPIFFS

AnimatedGIFs_SD
/System Volume Information
1:/test1.gif    size:711166
2:/test2.gif    size:173301
Animated GIF files Found: 2
Init complete
[0 frames = 0ms] actual: 1339ms speed: 0% plot: 0
Pathname: /test1.gif
Logical Screen [LZW=5 128x128 P:0xF4 B:27 A:0 F:10ms] frames:0 pass=1
[0 frames = 1200ms] actual: 10051ms speed: 11% plot: 1963904
Pathname: /test2.gif
Logical Screen [LZW=6 117x128 P:0xF5 B:14 A:0 F:70ms] frames:0 pass=1
[0 frames = 6790ms] actual: 10020ms speed: 67% plot: 1246381

No SD; included gifs from flash: white screen, lots of lines get dropped from drawLineCallbackbecause of the if (y >= tft.height() || x >= tft.width() ) test failing

AnimatedGIFs_SD
No SD card
teakettle_128x128x10_gif
globe_rotating_gif
bottom_128x128x17_gif
irish_cows_green_beer_gif
horse_128x96x8_gif
llama_driver_gif
Animated GIF files Found: 6
Init complete
[0 frames = 0ms] actual: 1259ms speed: 0% plot: 0
Flash: teakettle_128x128x10_gif size: 21155
Logical Screen [LZW=6 128x128 P:0xF5 B:0 A:0 F:80ms] frames:0 pass=1
[10 frames = 800ms] actual: 1004ms speed: 79% plot: 114859
Flash: globe_rotating_gif size: 90533
Logical Screen [LZW=8 170x170 P:0xD7 B:0 A:0 F:110ms] frames:0 pass=1
[30 frames = 3300ms] actual: 4222ms speed: 78% plot: 385792
Flash: bottom_128x128x17_gif size: 51775
Logical Screen [LZW=8 128x128 P:0xF7 B:0 A:0 F:70ms] frames:0 pass=1
[17 frames = 1140ms] actual: 1416ms speed: 80% plot: 185817
Flash: irish_cows_green_beer_gif size: 29798
Logical Screen [LZW=4 401x157 P:0xB3 B:15 A:0 F:600ms] frames:0 pass=1
[4 frames = 1600ms] actual: 1780ms speed: 89% plot: 65536
Flash: horse_128x96x8_gif size: 7868
Logical Screen [LZW=4 128x96 P:0xF3 B:0 A:0 F:80ms] frames:0 pass=1
[8 frames = 640ms] actual: 754ms speed: 84% plot: 76714
Flash: llama_driver_gif size: 758945
Logical Screen [LZW=8 355x200 P:0xF7 B:0 A:0 F:40ms] frames:0 pass=1
[108 frames = 4320ms] actual: 7135ms speed: 60% plot: 1483264

Here are my test files (optimized and scaled for the 128x128 TFT): test1 test2

Lastly if you would like to check my edits in further detail, here's my current sketch. I mostly removed code for other boards in order to make it easier to parse for me, added some debug, and made small edits eg used tft.drawColors in the drawLineCallback).

Cheers,

prenticedavid commented 4 years ago

Sorry. I have been doing other things. I have not forgotten you.

Both of your sample GIFs have substantial deltas. i.e. a lot of pixels change in each frame.

My sample GIFs tend to have fairly small rectangles that change.

David.

t0mg commented 4 years ago

Thanks David and no worries.

Yes I am aware that these gifs are rather heavy. But that isn't related to the white screen issue I'm experiencing (otherwise your sample GIFs should display). Would you have any clue on what might be wrong that could cause the images to only display when reading from spiffs?

prenticedavid commented 4 years ago

I will come back to you.

I have ESP32 and TFT_eSPI. I have ST7735 SPI. I have SPIFFS. I have your sample GIFs. So I can try it for myself (when I get around to it)

David.

prenticedavid commented 4 years ago

ST7735 is showing corrupted pixels with TFT_eSPI ILI9341 is showing corrupted pixels with TFT_eSPI

GIFs display nicely from PROGMEM on a parallel ILI9225 with MCUFRIEND_kbv on a fast STM32. There is no SD on the ILI9225 display. Your mad_race.gif runs well. Your mad_man.gif is not running at the correct speed.

I will rearrange the conditional libraries and target displays.

Then I will investigate what is corrupting displays. And see if I can improve the speed.

The speed depends on LZW decoding the GIF data. And the throughput of pixels to the display. If I can minimise the pixel traffic it will improve SPI display. If I send a whole line of pixels by DMA it might make a dramatic difference. (but only on frames with no SKIP pixels)

David.

prenticedavid commented 4 years ago

From SD card:

Pathname: /gifsdbg/mad_man.gif
Logical Screen [LZW=5 128x128 P:0xF4 B:27 A:0 F:10ms] frames:0 pass=1
142 frames in 1420ms. effective speed: 12% typ: 127x127 skip:0% tot:2319257
Pathname: /gifsdbg/mad_race.gif
Logical Screen [LZW=6 117x128 P:0xF5 B:14 A:0 F:70ms] frames:0 pass=1
119 frames in 8330ms. effective speed: 67% typ: 116x108 skip:0% tot:1497358

From PROGMEM:

Flash: mad_man_gif size: 711166
Logical Screen [LZW=5 128x128 P:0xF4 B:27 A:0 F:10ms] frames:0 pass=1
142 frames in 1420ms. effective speed: 34% typ: 127x127 skip:0% tot:2319257
Flash: mad_race_gif size: 173301
Logical Screen [LZW=6 117x128 P:0xF5 B:14 A:0 F:70ms] frames:0 pass=1
119 frames in 8330ms. effective speed: 83% typ: 116x108 skip:0% tot:1497358

I appear to have slightly different printf() format. SD works fine. It is an 8GB SanDisk.

The mad_man looks a bit fast on ESP32. But it is not the correct speed. The STM32 M7 shows it very fast.

This is my problem. I am attempting 100 FPS (10ms) which is clearly not how the PC shows it.

Both your mad_xxx examples avoid SKIP pixels. So would be good candidates for DMA. You can see how many pixels are drawn for each Animation.

David.

t0mg commented 4 years ago

Thank you for investigating this David! Yes I did notice that the mad_man seemed to play as fast as possible. It was not a steady rate nor the intended one. The 100FPS attempt explains it.

So both SD and PROGMEM work for you with ST7735? Did you only rearrange the conditional libraries? Also note that I don't get corrupted pixels at all on mine, just a white screen.

Thanks again for your help!

prenticedavid commented 4 years ago

I have made a dramatic improvement. The program structure was wrong.

There are 3 main factors:

  1. TFT drawing speed. e.g. efficient use of SPI displays. TFT_eSPI is good. Adafruit_ST7735 is crap.
  2. Fetching GIF data from PROGMEM, SPIFFS, SD card. SD library is pretty slow.
  3. GIF decoding. e.g. fast CPU

The ESP32 manages quite well with PROGMEM and SPIFFS. Teensy4.0 performs well on most GIFs. Even from SD card. Best with Parallel TFT.

I will do some tidying up. And Sync to GitHub.

David.

t0mg commented 4 years ago

Sounds like great news, thanks for the update. Looking forward to seeing the changes you made!

Cheers,

prenticedavid commented 4 years ago

I have made some massive changes.

I have put all the conditional TFT_libraries in one H file. 0xE8266 selects the appropriate TFT_eSPI whether ESP32 or ESP8266. You need to edit the USE_TFT_LIB.h file to suit your wiring. Nothing else.

If there is no SD card, it will display from PROGMEM. Edit FilenameFunctions.h to select SPIFFS vs PROGMEM

David.

p.s. I strongly recommend that you Fork the project. Then we can see each other's code.

t0mg commented 4 years ago

Wow, it does work out of the box for me now from PROGMEM, and my test gifs play very fast! Your code is also much easier to parse with the conditional libraries now neatly separated in the H file. Congratulations!

I still have a small issue: the SD card isn't being read. I think I need to clean up my libraries, I might have a conflict somewhere/not using the proper SD library. I'll post an update when I get it 100% working. And yes, I will likely fork your project once I've got everything working :)

Here's the serial output I'm getting with PROGMEM (as fallback for SD):

AnimatedGIFs_SD
No GIF files on SD card
mad_man_gif
mad_race_gif
Animated GIF files Found: 2
Flash: mad_man_gif size: 711166
142 frames @ 20ms  85% [426] typ: 127x127 avg: 23.5ms draw: 17.9ms 0%
Flash: mad_race_gif size: 173301
119 frames @ 70ms 100% [357] typ: 116x108 avg: 17.2ms draw: 14.0ms 0%

And with SPIFFS:

AnimatedGIFs_SD
1:/mad_man.gif    size:711166
2:/mad_race.gif    size:173301
Animated GIF files Found: 2
Pathname: /mad_man.gif
142 frames @ 20ms  39% [426] typ: 127x127 avg: 51.2ms draw: 17.9ms 0%
Pathname: /mad_race.gif
119 frames @ 70ms 100% [357] typ: 116x108 avg: 25.7ms draw: 14.0ms 0%

Cheers,