Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 07:02 24 Jun 2026 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : PicoMite Video player

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 11540
Posted: 04:53pm 16 Jun 2026
Copy link to clipboard 
Print this post

Here
RGB332 at 30fps from SDcard - coming in RC21. Will also work with buffered TFT drivers
You can already play RGB121 videos with the current release - see the manual

CONVERTER.pdf

File converter

vid2rgb121.zip

Sample video in RGB121


cartoon.zip


'============================================================
' RGB121 framebuffer video player  (companion to vid2rgb121.py)
'
' Fast path: each frame is read straight from the file into a RAM
' buffer with MEMORY INPUT (no INPUT$/LONGSTRING loop), then BLIT
' MEMORY decodes the RLE nibbles directly onto the LIVE screen
' (no framebuffer, no FRAMEBUFFER COPY).
'
' .vc frame layout on disk:
'     uint32  blobLen          (little-endian)
'     uint16  width | 0x8000    \  BLIT MEMORY header
'     uint16  height            /
'     bytes   rle...            (colour<<4)|count, count 1..15
'
' On HDMI/USB the base display must be 640x480; MODE 2 makes it a
' 320x240, 16-colour RGB121 surface:
'     OPTION RESOLUTION 640x480[,315000]   (one-off, persists)
'============================================================
Option EXPLICIT

Const F_HANDLER = 1
Const T_ESC     = 27
Drive "b:"
Dim STRING vidFile = "cartoon.121"
Dim STRING audFile = ""'"sample-2.aud"   ' set to "" if the clip has no audio
Dim FLOAT  fps     = 30               ' MUST match the converter's --fps
Dim FLOAT  frameMs = 1000 / fps
Dim INTEGER vDelay = 0                ' ms A/V sync nudge

' --- per-frame RAM buffer (NOT a long string: raw integer array) -----
' Holds one compressed frame blob (header + RLE). 320x240 worst case
' is ~76 KB; 9700 ints = 77.6 KB headroom.
Dim INTEGER buf%(9700)
Dim INTEGER baddr% = Peek(VARADDR buf%())   ' frame data address for BLIT MEMORY
Dim INTEGER lenbuf%(1)                        ' 16 bytes scratch for the length
word

' --- screen: MODE 2 draws straight to the live 320x240 RGB121 display
MODE 2
CLS

Dim INTEGER blobLen, frames = 0

Open vidFile For INPUT As #F_HANDLER
If audFile <> "" Then Play WAV audFile
Pause vDelay

Timer = 0
Do
 If Eof(#F_HANDLER) Then Exit Do

 ' --- read the 4-byte little-endian blob length straight into RAM ---
 lenbuf%(0) = 0
 Memory INPUT F_HANDLER, 4, lenbuf%()
 blobLen = lenbuf%(0)                 ' low 4 bytes = length, upper pre-zeroed

 ' --- read the whole frame blob in one go, then decode onto screen ---
 Memory INPUT F_HANDLER, blobLen, buf%()
 Blit Memory baddr%, 0, 0
 frames = frames + 1

 ' --- pace to the encode fps so audio stays in sync (drift-free) ---
 Do While Timer < frames * frameMs
 Loop

 If Asc(Inkey$) = T_ESC Then Exit Do
Loop

Close #F_HANDLER
Play STOP
Print "Played "; frames; " frames in "; Str$(Timer/1000); " s"
End
 
dddns
Guru

Joined: 20/09/2024
Location: Germany
Posts: 848
Posted: 08:27am 22 Jun 2026
Copy link to clipboard 
Print this post

I have tested this with an ILI9341 and it runs perfectly smooth. Then I created a short (true-colour) clip and used vid2rgb121.py to convert. I had no errors and the converted clip played fine as well.

Of cause the colours of a true-colour image don't look good when converted to RGB121..

Could vid2rgb121.py be changed to allow diffent colour depths (for LCD) or could there be an option that each frame is dithered before it gets appended?
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 11540
Posted: 08:56am 22 Jun 2026
Copy link to clipboard 
Print this post

vid2rgb121.py already supports RGB332, this will play in mode 5 HDMI or using one of the buffered TFT drivers.

CONVERTER.pdf

cartoon.zip


'============================================================
' RGB121 framebuffer video player  (companion to vid2rgb121.py)
'
' Fast path: each frame is read straight from the file into a RAM
' buffer with MEMORY INPUT (no INPUT$/LONGSTRING loop), then BLIT
' MEMORY decodes the RLE nibbles directly onto the LIVE screen
' (no framebuffer, no FRAMEBUFFER COPY).
'
' .vc frame layout on disk:
'     uint32  blobLen          (little-endian)
'     uint16  width | 0x8000    \  BLIT MEMORY header
'     uint16  height            /
'     bytes   rle...            (colour<<4)|count, count 1..15
'
' On HDMI/USB the base display must be 640x480; MODE 2 makes it a
' 320x240, 16-colour RGB121 surface:
'     OPTION RESOLUTION 640x480[,315000]   (one-off, persists)
'============================================================
Option EXPLICIT

Const F_HANDLER = 1
Const T_ESC     = 27
Drive "b:"
Dim STRING vidFile = "cartoon.332"
Dim STRING audFile = ""'"sample-2.aud"   ' set to "" if the clip has no audio
Dim FLOAT  fps     = 30               ' MUST match the converter's --fps
Dim FLOAT  frameMs = 1000 / fps
Dim INTEGER vDelay = 0                ' ms A/V sync nudge

' --- per-frame RAM buffer (NOT a long string: raw integer array) -----
' Holds one compressed frame blob (header + RLE). 320x240 worst case
' is ~76 KB; 9700 ints = 77.6 KB headroom.
Dim INTEGER buf%(9700)
Dim INTEGER baddr% = Peek(VARADDR buf%())   ' frame data address for BLIT MEMORY
Dim INTEGER lenbuf%(1)                        ' 16 bytes scratch for the lengthword

' --- screen: MODE 2 draws straight to the live 320x240 RGB121 display
MODE 5
CLS

Dim INTEGER blobLen, frames = 0

Open vidFile For INPUT As #F_HANDLER
If audFile <> "" Then Play WAV audFile
Pause vDelay

Timer = 0
Do
If Eof(#F_HANDLER) Then Exit Do

' --- read the 4-byte little-endian blob length straight into RAM ---
lenbuf%(0) = 0
Memory INPUT F_HANDLER, 4, lenbuf%()
blobLen = lenbuf%(0)                 ' low 4 bytes = length, upper pre-zeroed

' --- read the whole frame blob in one go, then decode onto screen ---
Memory INPUT F_HANDLER, blobLen, buf%()
Blit Memory332 baddr%, 0, 0
frames = frames + 1

' --- pace to the encode fps so audio stays in sync (drift-free) ---
Do While Timer < frames * frameMs
Loop

If Asc(Inkey$) = T_ESC Then Exit Do
Loop

Close #F_HANDLER
Play STOP
Print "Played "; frames; " frames in "; Str$(Timer/1000); " s"
End
 
dddns
Guru

Joined: 20/09/2024
Location: Germany
Posts: 848
Posted: 09:24am 22 Jun 2026
Copy link to clipboard 
Print this post

Thank you! I will update to RC23 and then report back
 
dddns
Guru

Joined: 20/09/2024
Location: Germany
Posts: 848
Posted: 01:00pm 22 Jun 2026
Copy link to clipboard 
Print this post

Thank you for the RGB332 player. It works fine with an ILI9341 setup and RGB332-rle.
I converted a 1,9Mb source file and got a 7,6Mb output. Audio conversion with default parameters also worked well:
python3 vid2rgb121.py ./small.mp4 sample_rle.332 --w 320 --h 240 --fps 25 --rgb332-rle
 200 frames, 6661 KB
Done: 218 frames, 7447.3 KB -> sample_rle.332
Audio: mono 22050 Hz 8-bit -> sample_rle.aud (188 KB)

Format: RGB332 count+value RLE, MODE 5 (~2.2x vs raw). Needs the RGB332-RLE firmware decoder.
 totalFrames = 218
 vidFile = "sample_rle.332"
 audFile = "sample_rle.aud"   (PLAY WAV)
 pace frames to 25 fps so audio stays in sync (targetTime = 40.00 ms/frame)

On the Pico, the video and the colours look ok and sound works good :
RUN
Played  218 frames in 8.898157 s
> 218/8.898157
24.49945534
>
> option list
PicoMite MMBasic USB RP2350B Edition V6.03.00RC23
OPTION SERIAL CONSOLE COM2,GP8,GP9
OPTION SYSTEM SPI GP2,GP3,GP0
OPTION LCD SPI GP14,GP15,GP12
OPTION SYSTEM I2C GP4,GP5
OPTION FLASH SIZE 16777216
OPTION COLOURCODE ON
OPTION KEYBOARD US, 0, 0, 250, 50
OPTION PICO OFF
OPTION CPUSPEED (KHz) 384000
OPTION LCDPANEL ILI9341BUFF, LANDSCAPE,GP16,GP17,GP18,GP11
OPTION TOUCH GP13,GP19
OPTION SDCARD GP10
OPTION KEYBOARD REPEAT 250,50
OPTION AUDIO GP6,GP7', ON PWM CHANNEL 3
OPTION RTC AUTO ENABLE
OPTION DEFAULT FONT 7, 1
OPTION PSRAM PIN GP47


I couldn't get it to work with RGB332 Raw:

[57] Memory INPUT F_HANDLER, blobLen, buf%()
Error : Source array too small

The header of the Python script contains the usage but not mentioning all parameters.

With the RGB121 player it also runs with the ILI9341 standard driver.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 11540
Posted: 01:12pm 22 Jun 2026
Copy link to clipboard 
Print this post

  Quote  Error : Source array too small


That might give you a clue
In raw form for 320x240 the array needs to be 320x240+8 bytes == DIM array%((320*240)\8) assuming base 0
 
dddns
Guru

Joined: 20/09/2024
Location: Germany
Posts: 848
Posted: 01:53pm 22 Jun 2026
Copy link to clipboard 
Print this post

  matherp said  
That might give you a clue

Not really but it's hot in Germany :))
I thought it is this line:
Dim INTEGER buf%(9700)

But no matter how big it is dimmed it gives an error. First it will complain about too less heap. With PSRAM it keeps giving this error, I tried up to irrational high values..

But this was just a report, using Raw is not necessary as RLE compression runs fine and file sizes are 3x smaller..
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2026