FMV on Pokitto!

I recently managed to get full screen video streaming on the Pokitto handheld device.

For those of you who are interested in how I did that, here is a quick explanation…

I extracted the individual frames from a movie file using ffmpeg. The following windows .bat file first evaluates the video and creates a 256 colour table, this is part of the secret. Olny 256 colours are used for the whole video, no changes at any point. Next it extracts every frame to a single .bmp file using the palette it created in the first step.

mkdir frames
set start_time=0
set palette="palette.png"
set filters="vflip,fps=20,scale=110:88:flags=lanczos"
ffmpeg -v warning -ss %start_time% -i %1 -vf "%filters%,palettegen" -y %palette%
set var1=%1
set var2=%var1:~0,-4%
ffmpeg -v warning -ss %start_time% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y frames/%%d.bmp

 

The next step I used a short blitzbasic program to collect the palette and all of the different image data into a single file…

 

Graphics 640,480,0,2

frameNumber = 1
Dim pal(3,256)

a$ = "D:\blitz\pokitto\frames\"

outfile = WriteFile("movie.dat")

.top

Cls
Text 0,0,infile$
;infile$=a$+Right$("000"+frameNumber,3)+".bmp"
infile$=a$+frameNumber+".bmp"
Text 0,12,infile$

picture = OpenFile(infile$)

If picture Then

gfx=LoadImage(infile$)
DrawImage gfx,0,24 ; Draw the image!

If frameNumber = 1 Then
; if first file, grab the palette
SeekFile(picture,54)
; pal = 4x256
For t=0 To 255
pal(2,t) = ReadByte(picture)
pal(1,t) = ReadByte(picture)
pal(0,t) = ReadByte(picture)
temp = ReadByte(picture)
WriteByte(outfile, pal(2,t))
WriteByte(outfile, pal(1,t))
WriteByte(outfile, pal(0,t))
Next
Else
; if not, skip it
SeekFile(picture,54+(256*4))
EndIf

y=0
x=0
For t=1 To 112*88
temp = ReadByte(picture)
If(x<110) Then
WriteByte(outfile, temp)
;Color pal(0,temp),pal(1,temp),pal(2,temp)
;Plot x+200,88-y
End If
x = x + 1
If x = 112 Then
x = 0
y = y + 1
End If
Next

CloseFile picture

frameNumber = frameNumber + 1

Goto top

End If

CloseFile outfile

 

To test that the video had formed correctly I created a test program, also in blitzbasic…

Graphics 640,480,0,2

frameNumber = 1

infile$="movie.dat"
Dim pal(3,256)

stream = OpenFile(infile$)

While Not Eof (stream)

If frameNumber = 1 Then
For t=0 To 255
pal(2,t) = ReadByte(stream)
pal(1,t) = ReadByte(stream)
pal(0,t) = ReadByte(stream)
;d = ReadByte(stream)
Next
EndIf

x=0
y=0
For t=1 To 110*88
temp = ReadByte(stream)
Color pal(0,temp),pal(1,temp),pal(2,temp)

Rect x*5, (88-y)*5, 5,5,1
; Plot x,88-y
x = x + 1
If x = 110 Then
x = 0
y = y + 1
End If
Next

frameNumber = frameNumber + 1
; Delay (1000/15)

Wend

CloseFile stream

 

Then the last step, getting it running on the Pokitto…

Note that this code requires an update to mode13, which may not be in the main pokittolib at this point in time, but the changes can be found here.

 

/** Mode 13 (110x88x256) by Spinal, a palette rotating plasma demo */

#include "Pokitto.h"
#include "SDFileSystem.h"

SDFileSystem sd(/*MOSI*/P0_9, /*MISO*/P0_8, /*SCK*/P0_6, /*CS*/P0_7, /*Mountpoint*/"sd");

Pokitto::Core game;

unsigned short pal[256]; // assign a 256 entry array to hold the palette

int main(){
game.begin();
game.display.persistence=1;
game.setFrameRate(999);

int temp;
pokInitSD(); // Call init always.

while (game.isRunning()) {

uint32_t myFile = fileOpen("movie.dat", FILE_MODE_READONLY);
if( !myFile ){

unsigned char col[3];
uint16_t tempPal[256];
for(temp=0; temp<256; temp++){
fileReadBytes(&col[0], 3);
pal[temp] = (col[0]>>3) | ((col[1] >> 2) << 5) | ((col[2] >> 3) << 11);
}
game.display.load565Palette(&pal[0]); // load a palette the same way as any other palette in any other screen mode
bool stillGoing=1;
while(stillGoing==1){
if(game.update()){
if(!fileReadBytes(&game.display.screenbuffer[0], 9680))stillGoing=0;
}
}
fileClose();
} // file open

}

return 1;
}