[Coladam] project idea : 30 seconds video into a 32K Coleco game.

Daniel Bienvenu newcoleco at yahoo.fr
Wed Apr 18 03:05:29 EDT 2007


Hello,

In the past, I did a codec to play a "tiny video
sequence" on a ColecoVision.
The project works fine but we can certainly do better.
My personal goal is about 30 seconds "movie trailer"
of video in 32K (including the software to play it).
Give your opinion about this project idea.
Who is good in data compression and image processing?
Knowledge and advice are welcome.


New ColecoVision video codec project
starting date : 2007-04-18

Synopsis
========

Text about how it's possible to show a short video
(coded in ROM) on a ColecoVision game system.

Goal
====

Be able to add video in new Coleco games.

Basis
=====

ROM space is 32K including software to play the video
and the video itself.
RAM space is less than 1K.
Video set to mode 0 (Graphic I) to show hi-res
monochrome video.
(variation : Video set to mode 3 (Multicolor) to show
low-res multicolor video.)

Information
===========

The basic approch is two softwares : an encoder and a
decoder.
The encoder is running on your actual computer to
convert data from a video clip.
The decoder is running on ColecoVision to read the
data and show the result on screen.
The main part of this project is to optimize the
encoder to minimize data to be in ROM.

I split the encoded video in two formats and two
cathegories:

- FULL (alias full screen) 128x96 pixels (16x12
characters of 8x8 pixels, ratio 4:3)
- WIDE (alias wide screen) 128x72 pixels (16x9
characters of 8x8 pixels, ratio 16:9)
- NORMAL (alias normal speed) 5 frames per second (1
frame = 10 PAL cycles, 12 NTSC)
- SUPER (alias super speed) 10 frames per second (1
frame = 5 PAL cycles, 6 NTSC)

Suppose 384 bytes in RAM to manipulate data to be on
screen.
A frame in wide format will take 4 cycles, 5 cycles
when it's full format.
5 cycles to prepare the next frame is equal to the
minimum 5 cycles per frame (PAL).

NMI
---
3 steps to be done per needed cycle :
- STEP 1 : READ DATA FROM VRAM (read 384 bytes from
frame actually showed on screen)
- STEP 2 : TRANSFORM DATA (prepare next frame by
decoding ROM data)
- STEP 3 : WRITE DATA TO VRAM (write 384 bytes to next
frame to be showed on screen)
- STEP 4 : SWAP SCREEN TO SHOW NEW FRAME WHEN READY

Note : STEP 1 gives the opportunity to not use only
data from ROM for next frame.

Because there is an ideal time to access to VRAM, that
is at the NMI entry point,
step 3 have to be done in the next cycle. This way no
bug NMI versus VRAM.

If we rename STEP 1,2 and 3 by STEP A, B and C, we can
show the needed cycles like this.

SUPER WIDE (NTSC) result for 2 frames :
123456789012
.AAA...AAA..
BBB...BBB...
CCC...CCC...

SUPER FULL (NTSC) result for 2 frames :
123456789012
.AAAA..AAAA.
BBBB..BBBB..
CCCC..CCCC..

SUPER WIDE (PAL) result for 2 frames :
1234567890
.AAA..AAA.
BBB..BBB..
CCC..CCC..

SUPER FULL (PAL) result for 2 frames :
1234567890
.AAAA.AAAA
BBBB.BBBB.
CCCC.CCCC.

PROBLEM TO SOLVE
----------------
Encoded DATA in ROM have to be simple enough to be
decoded in time by the console.
Encoding each frame perfectly (lossless compression)
will take too much ROM.

NOTATION
--------
Frame 0 : first frame
Frame 1 : second frame
Frame N : Nth frame

SUGGESTIONS
-----------

MINIMIZE NUMBER OF CHARACTERS (8x8 pixels) TO MODIFY
....................................................
To minimize the amount of data needed per frame, we
have to minimize first the
number of characters to update. To do that we have to
answer simple questions like
"which part of the next frame is the most important to
be necessary updated now?" 

The following is a pseudocode that can be used to
select characters to update.

max_characters = ***
max_pourcent_error = ***
for each new frame N:
.. init a priority list (or tree)
.. for each character:
.... A = compute difference (% error) between frame
N-1 and frame N
.... B = compute difference (% error) between frame
N-1 and frame N+1
.... C = compute difference (% error) between frame N
and frame N+1
.... IF (C is less than A) or (C is less than B) THEN
...... set priority 1 for this character
.... ELSE
...... IF A is over the defined limit THEN
........ set priority 2 for this character
...... ELIF A is under the defined limit THEN
........ set priority 3 for this character
...... ELSE
........ set no priotity for this character
.. now encode only the first X characters sorted in
the priority list (or tree)

MINIMIZE THE NEW DATA
.....................
To minimize the needed data to encode the characters,
we need compression technics.
Some technics cost more in CPU, others cost more in
DATA, difficult to decide.
To avoid using ROM for software, we can't implement
many technics.

The following is a description of data structure for
the encoded video in ROM.

video = [format][speed][length of
data][frame0][frame1][frame2]...[last frame]
frame = [flags that decide which chars to
update][compressed data]

flags : the FULL and WIDE formats are both 16
characters large, that result into
 16 flags per line of chars, 8 bits per byte, so two
bytes to encode these flags.
That means 18 bytes for WIDE format and 24 bytes for
FULL format.
So, a maximum of 24 bytes per frame to say "these
chars to update"

data : the compression technic can be a dictionnary
where you just say
where to take data in the entire encoded video. And
rather than just point to
new data that is exactly what you want, we can point
to old data that is similar
to avoid encoding 8 bytes per character for every
single frame. And if it's not enough,
we can try applying filters like AND, OR and XOR to
transform the actual pattern
to a new one by applying bit-to-bit operation technics
with old data.

If we say that white pixels are 1s and black pixels
are 0s.
- AND operation will make the new pattern darker (more
black pixels)
- OR operation will make the new pattern brighter
(more white pixels)
- XOR operation will result into anything from no
change to reverse pixels.

Table of available filters (transformations) coded in
two bits
00 : replace without using bit operator
01 : do OR
10 : do AND
11 : do XOR

Operator (filter) code plus the relative pointer to
data can be coded into two bytes.
We can also put all data that represent pattern
outside the frame data to be a common part.

Well, that's all for now. Don't hesitate to contribute
to the project.

Daniel


      
___________________________________________________________________________ 
Découvrez une nouvelle façon d'obtenir des réponses à toutes vos questions ! 
Profitez des connaissances, des opinions et des expériences des internautes sur Yahoo! Questions/Réponses 
http://fr.answers.yahoo.com



More information about the Coladam mailing list