Forum: Mikrocontroller und Digitale Elektronik AVR: Video-Codec für kleines Intro oder Screensaver


von Sebastian (Gast)


Lesenswert?

Hallo!

Ich möchte mittels AVR auf einem Pictiva OLED-Display ein kleines 
Intro-Video anzeigen lassen. Wenn man das fertig programmiert hat, kann 
man das natürlich auch für z.B. Screensaver verwenden (bei OLED übrigens 
sehr vorteilhaft wegen Pixel-Verdunklung nach einer gewissen Zeit!)

Ich habe mir das so vorgestellt:

Verwende ein 256x64 - Display
Möchte etwa 4 Sekunden mit 15 Bildern / Sekunde anzeigen --> 60 Bilder
Folglich ergeben sich für die Rohdaten (4bit/px):
256 x 64 x 1/2 x 60 = ca. 490 KB
Viel zu viel!
Also: Video kodieren. Und ein Video-Decoder für den AVR muss her!
Möglichst einfach, wenig Code, wenig RAM, wenig Rechenzeit. Nicht 
unbedingt soooo leistungsstark was die komprimierung angeht.
Hab im Internet sehr wenig gefunden.
Sogar der quasi einfachste Codec, der gut verbreitet ist, MPEG, ist 
schon viel zu kompliziert. Wenn ich mir dazu doc's durchlese verstehe 
ich nur Bahnhof...

Also einen ganz eigenen Codec selbst programmieren.
Mir fielen gleich ein paar Dinge ein, wo man bei Videos Daten sparen 
kann: Gleiche benachbarte Pixel.
Dafür hab ich ein Frame (256x64) in 32x32-große "Blocks" zerlegt.
Jeder Block wird einzeln und unabhängig von anderen kodiert.
Ein Block kann jetzt z.B. nur Pixel mit gleicher Farbe enthalten.
Habe das mit einem Test-Video gemacht: ca. 60% aller Blocks haben die 
gleiche Farbe.
Dann gibt es Blöcke, die, wenn man sie nochmals unterteilt, teilweise 
ebenfalls nur aus Flächen gleicher Farbe bestehen.
Dafür muss ein Block nun in etwa 4x4-große "Sub-Blocks" unterteilt 
werden.
Soweit bin ich noch nicht mit dem Programmieren.

Hab mir gedacht ich schildere euch mein Problem und vllt finden es 
andere hier im Board auch mal ganz interessant, einen Codec zu proggen, 
immerhin kann man damit einiges machen!

Ich hoffe, dass ich somit ein Video von ursprünglichen 490KB auf ca. 
50KB bekomme. (habe 128K Flash)
Dabei muss es nicht unbedingt verlustfrei kodiert werden! (So käme man 
nicht sehr weit)

Vielleicht haben andere hier noch Ideen, wie man einen Codec gestalten 
kann.


MfG,
Sebastian

von Marko (Gast)


Lesenswert?

Viele Codecs verwenden Schlüsselbilder, die die Information eines ganzen 
Bildes enthalten. Die nachfolgenden Bilder enthalten nur noch die 
Änderungen
jeweils von Bild zu Bild, also deutlich weniger Information, da sich ja 
nicht immer alle Pixel ändern.
Als Speicher käme mir da ne SD-Karte in den Sinn, der Vorteil währ dann, 
dass du recht einfach das Video updaten kannst. Der lesezugriff sollte 
schnell genug sein und die Animationslänge würde nur durch den Speicher 
der Karte begrenzt.

von Sebastian (Gast)


Lesenswert?

Hallo!
Danke für die schnelle Antwort.
Ja, ne SD kam mir auch schon in den Sinn, doch hab ich wenig Platz für 
sowas... Wenn dann miniSD oder so. Aber dennoch möchte ich nicht ein 
unkomprimiertes Video verwenden. Allein der Spaß am Programmieren ist 
genug was für den Codec spricht! ;-)

Ja ich weiß was du meinst.
I-Frames speichern ein komplettes Frame (Bild)
Dazwischen lauter Frames, von denen die Änderung gespeichert wird.
Quasi alle Codecs verwenden hier eine Unterteilung, so wie ich es 
beschrieben habe. Dadurch lassen sich zeitliche Verschiebungen "klein" 
kodieren:
Z.B. wenn ein Text durch das Bild wandert, dann verschiebt er sich ja 
nur, und es kommen an einer Seite neue Pixel "herein".
Es werden dann lauter Quadrate im I-Frame gespeichert,
Diese können in den darauffolgenden Frames verschoben oder geändert 
werden.
Es fragt sich nur, wieviel Rechenaufwand man dafür benötigt.

Leider muss man aber im AVR die I-Frames, bzw. immer das letzte Bild 
merken, um das nächste Bild zu berechnen.
Dafür braucht man aber 256 x 64 x 1/2 = 8KB Daten!
Leider haben alle AVR's max. 4KB RAM, und für einen externen hab ich 
ebenfalls wenig Platz.
Außerdem weiß ich nix über externe RAMS, weder wo's die gibt, wie die 
heißen, noch wie man die ansteuert.

Deswegen denke ich, ist es die beste Lösung, wenn man nur einzelne 
Bilder kodiert.

MfG,
Sebastian

von jmoney (Gast)


Lesenswert?

Wie wär's, wenn du nach einem key-frame die Änderungen so speicherst, 
wie sie übertragen werden sollen? Dann musst du nur beim "encodieren" 
das vorangegangene Bild im RAM halten. Ist dann natürlich nicht mehr 
geeignet, um live Einblendungen zu machen. Dafür müsste man natürlich 
doch einen Teil des Bildes im RAM halten..

Bsp:

-steuerzeichen für "jetzt kommt key frame"

key frame Daten

-steuerzeichen für "nur änderungen"

//zeile  spalte  byte
    1       5    0xFF
    5       45   0x0A
    21      17   0x32

-steuerzeichen für nächsten frame

von fnah (Gast)


Lesenswert?

sehr einfach und schnell zu decodieren:
http://en.wikipedia.org/wiki/PackBits

von Sebastian (Gast)


Lesenswert?

@jmoney:
Bezüglich des RAMs:
Naja enkodieren soll der AVR nicht können. Was soll denn der kodieren? 
Mir fällt keine Einsatzmöglichkeit ein. Aber machbar wäre es schon...

Bezüglich den Änderungen:
So ähnlich hab ich mir das auch vorgestellt.
Die Änderungen würde ich allerdings so wie ich es geschrieben habe 
blockweise kodieren, da man sonst je Pixel viel zu viele Daten hat: 8bit 
Spalte + 6bit Zeile + 4bit Farbe = 18bit statt nur 4bit!



Kodierung eines I-Frames UND eines Änderungsframes:

I-Frame: Bild wird in beliebig große (quadratische) Blöcke zerlegt, die 
nicht unbedingt das gesamte Bild abdecken müssen: Leere Bereiche werden 
schwarz dargestellt. (Vorher einfach Bild schwarz machen, dann Blöcke 
draufmalen)

Zwischenframes: Es werden geänderte Pixel so in Blöcke unterteilt, dass 
sie alle geänderten Pixel einschließen (natürlich noch ein paar andere, 
das schadet ja nicht...)


Beim Kodieren eines Blockes würd ich das jetzt, nach nochmaligem 
überlegen, so machen:

Erst die Position: 8bits Zeile, 4bits Spalte (bei anderen Auflösungen 
kann man allgemein jeweils 1Byte verwenden)

Es gibt verschiedene Blockgrößen, immer Zweierpotenzen, würde spontan 
2x2, 4x4, 8x8 und 16x16 vorschlagen. Dann hat man gerade mal 2bit Daten 
für die Größe.

Dann könnte man verschiedene Farb-Modi festlegen: 2 Farben indiziert, 4 
Farben indiziert, 4 Farben konstant (jede vierte), 8 Farben indiziert, 8 
Farben konstant (jede zweite) und alle 16 Farben. Da es hier 6 
Möglichkeiten gibt, werden hierfür 3bit benötigt.
Bei indizierten Modi folgen natürlich erstmal die Farben der Palette, je 
Farbe natürlich 4bit. Ergeben dann nicht sehr viel Daten. 4 Farben: 2 
Bytes, 8 Farben: 4 Bytes. Indizierte Paletten lohnen sich aber trotzdem 
erst ab größeren Blöcken.

Je Pixel braucht man dann - je nach Farbmodus natürlich - 1 bis 4 bits 
Farbdaten.



@fnah:
Aha interessant... Hm... hab mich gleich mal in der Kategorie "Lossless 
compression algorithms" umgeschaut und bin auf den bekannten LZ77-Codec 
gestoßen. Der geht nach einer Methode, bei der ganze Folgen an Bytes 
wiederholt werden können (werden in einer Tabelle angelegt). Gibts auch 
im deutschen Wiki. Vielleicht wäre der ein bisschen besser, doch etwas 
komplizierter. Muss man sich mal näher anschauen.

Ich würde aber solche RLE-Kodierungen im Nachhinein über den Bytestream 
laufen lassen. Beim Decoden kommt das natürlich an erste Stelle und 
ermöglicht hoffentlich ein reibungsloses, direktes Lesen ohne vorher 
alles nochmal zwischenzuspeichern. Dürfte vor allem beim PackBits kein 
Problem sein.



Wer ist mit dran interessiert, sowas gemeinsam zu programmieren?
Wenn ich fertig bin würde ich es so oder so als OpenSource 
veröffentlichen...

Noch was: So wie es bis jetzt aussieht wird das wohl doch lossless... 
Muss aber nicht unbedingt sein. Wollte das nur nochmal erwähnen. Ein 
verlustbehafteter Codec scheint wohl nicht einfach zu sein!

MfG,
Sebastian

von Simon K. (simon) Benutzerseite


Lesenswert?

Zwar schon in etwa von Sebastian erwähnt, aber hier vielleicht noch ein 
hilfreicher Link der englischen Wikipedia, wo mehrere Lossless-Codecs 
für Videos aufgelistet sind:

http://en.wikipedia.org/wiki/Lossless_data_compression#Video_compression

Btw, hast du dir schonmal png-compression angeguckt?

von Sebastian (Gast)


Lesenswert?

Vor allem der erste Codec, der Animation Codec, hört sich gut an:
"playback of uncompressed RGB video in real time without expensive 
hardware"; "uses run-length encoding"...

von jmoney (Gast)


Lesenswert?

>@jmoney:
>Bezüglich des RAMs:
>Naja enkodieren soll der AVR nicht können. Was soll denn der kodieren?
>Mir fällt keine Einsatzmöglichkeit ein. Aber machbar wäre es schon...

Sorry, das war missverständlich ausgedrückt. Das Video wird natürlich im 
PC codiert. Der hat ja genug RAM..

>Bezüglich den Änderungen:
>So ähnlich hab ich mir das auch vorgestellt.
>Die Änderungen würde ich allerdings so wie ich es geschrieben habe
>blockweise kodieren, da man sonst je Pixel viel zu viele Daten hat: 8bit
>Spalte + 6bit Zeile + 4bit Farbe = 18bit statt nur 4bit!

Wenn in einem Frame nur 10 Pixel geändert werden, sind das 180 bit im 
Vergleich zu 256  64  4 = 64kbit.
Das Verfahren lohnt sich also bis 64k / 18 = 3640 veränderten Pixeln. 
Beim Beispiel Text durchlaufen hat man maximal 256 * 7 = 1792 für eine 
komplette Zeile. Bei echtem Text wird es wohl etwas weniger sein aber da 
stößt das Verfahren zugegebenermaßen schon an seine Grenzen. Für eine 
kleine Animation, wo ein Punkt durch's Bild hüpft oder sowas wäre die 
Kompressionsrate schon enorm hoch.

Der Blockansatz lohnt sich gegenüber meinem, sobald mehr als einem 
benachbarte Pixel geändert werden müssen, wenn ich das richtig 
verstanden habe. 8-nZeile + 6-mSpalte + 2^n*2^m*4Farbe gegenüber 
2^n*2^m*18

Bei n=m=1 (also Blockgröße 2x2 Pixel) braucht ein Block 30 bit (Plus 1 
oder 2 weitere, wenn verschiedene Blockgrößen eingeführt werden). Klingt 
sinnvoll.

Mit dem angesprochenen PackBits könnte man wohl aus beiden Ansätzen noch 
einiges mehr rausholen.

von jmoney (Gast)


Lesenswert?

>sobald mehr als einem benachbarte Pixel

soll 2 oder mehr heißen

von Frank J. (frajo)


Lesenswert?

Das mit den Blöcken klingt fast wie theora. Kennst Du das?
http://theora.org/doc/Theora_I_spec.pdf

von Sebastian (Gast)


Lesenswert?

@Frank:
Klingt nicht schlecht, bin mal das Inhaltsverzeichnis durchgegangen.
Morgen hab ich mehr Zeit, da les ich mir mal einiges durch.
Wird hier EIN codec vorgestellt oder allgemein Theorien zur 
Video-Kodierung?

@jmoney:
Ja soweit sind die Beispielrechnungen richtig.
Ich möchte hauptsächlich 3D-Animationen (Drehungen, Bewegungen, Text, 
Zoomen) verwenden. Da lohnt es sich nicht, pixelweise das Bild 
aufzubauen. Bei einem springenden Pixel wäre das natürlich was anderes, 
obwohl ich genau für sowas diesen 2x2-Block einführen will, mit einem 
minimalen Header: da 4 Pixel recht wenig Daten gegenüber einem Header, 
in dem die Farbtabelle oder andere Infos gespeichert werden, recht wenig 
Daten brauchen, werde ich 2x2-Blöcke stets im 4bit-Modus kodieren. Somit 
benötigt ein einzelner einsamer Pixel ohne Nachbarn diese 14bit für die 
Koordinaten, den "Block-Code", also die Größe des Blocks: 2bit, und 2 
Bytes für die 4 Pixel. Also 14+2+16=32bit. Auch nicht die Welt. Daher 
denke ich lohnt es sich kaum, 2 Kodierungsvarianten einzuführen. Würde 
nur den AVR-Decoder-Code aufblähen.

Ich mach mich mal morgen und übermorgen ran, ein bisschen die Blocks zu 
coden. Ein relativ schwieriger Teil wird das Erkennen der 
bestmöglichsten Kodierung werden. Da mach ich es wohl so, dass 
hauptsächlich "rumprobiert" wird. Bei so kleinen Videos schadet es ja 
nicht, wenn man mit nur 1 Frame pro Sekunde kodiert... :-)

MfG,
Sebastian

von Frank J. (frajo)


Lesenswert?

Sebastian wrote:
> Wird hier EIN codec vorgestellt oder allgemein Theorien zur
> Video-Kodierung?

Es wird Theora beschrieben. Hab auch nicht alles gelesen. Konnte mich 
nur noch an die Zerlegung in Blöcke und Unterblöcke erinnern. Da Du das 
auch machst, dachte ich, es hilft.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Das wird in praktisch jedem Videocoder gemacht, hauptsächlich wegen der 
Bewegungskompensation (welche auf dem AVR aber eher wenig Sinn macht).

von Kai S. (Firma: ZeuSWarE GmbH) (zeusosc)


Lesenswert?

Hoi,..
Es gibt noch ne andere möglichkeit,..
http://www.digitalcraft.org/?artikel_id=397

so muss man nÜx codieren und spart platz,.. (aber auch aufwendig)
grüüüße

von Sebastian (Gast)


Lesenswert?

@Kai Scheddin
Dir ist schon klar, dass ich dann eine Grafikkarte mit OpenGL oder 
DirectX, einen Prozessor mit >500MHz und viiiiiiiel RAM (ca 200MB) 
brauche?
Das wäre die wohl sinnloseste "Kodierung" eines Films. Das sind gar 
keine kodierte Videos sondern 3D-Animationen, d.h. ein ausführbares 
Programm mit lauter Koordinaten, Farbmuster, Sample-Musik usw. die alle 
erstmal Daten für Texturen, Objekte und die Musik generieren müssen und 
dann noch von OpenGL oder DirectX dargestellt werden müssen...
Aber trotzdem Danke...

von Marko (Gast)


Lesenswert?

Eins der größten Probleme sind wenn ichs recht verstanden habe
einfach der Platz. Ram anhängen an den AVR ist im Prinzip nix
wildes, hab mal nen SIMM30 EDO angepfriemelt mit 1MB, das funzt
prima, aber der Riegel muss halt irgendwo hin und wenns für
nen SD-Chip nicht reicht gehts scheinbar schon eng zu.
Die einzige Möglichkeit, die ich sehe währe n µC verwenden,
der eben intern entsprechend RAM vorrätig hat, aber beim AVR
wird man mit mehr als 8K RAM kaum fündig werden (hab da aber
auch nicht alle Typen im Kopf, lass mich gern belehren)
Ich seh da eher den Weg in ARM weisen ... hätt dann auch
was Rechneoperationen angeht mehr Power.

von Rüdiger K. (sleipnir)


Lesenswert?

Marko wrote:
> Viele Codecs verwenden Schlüsselbilder, die die Information eines ganzen
> Bildes enthalten. Die nachfolgenden Bilder enthalten nur noch die
> Änderungen
Das mit den Änderungen ist richtig, das mit den Schlüsselbildern nicht. 
MPEG und Konsorten verwenden eine sog. Bewegungsprädiktion, d.h. sie 
versuchen das aktuelle Bild aus dem Vorgängerbild zu prädizieren (im 
einfachsten Falle durch zusammenpuzzeln aus Blöcken) und übertragen dann 
nur das JPEG-codierte Differenzbild.
Selbst wenn er eine Transformationscodierung und eine 
Bewegungsprädiktion macht fehlt aber noch ein Entropiecodierer, der die 
eingesparte Redundanz/Irrelevanz auch wirklich einspart!
Mein Vorschlag wäre als "Brutallösung": Bitauflösung durch entsprechende 
Quantisierung reduzieren. Wenn er mit 4 Farben auskommt kann er 4 Pixel 
in einem Byte unterbringen.

von Kai S. (Firma: ZeuSWarE GmbH) (zeusosc)


Lesenswert?

@Sebastian
Ja, das ist es,.. der gedanke daran animationen zu basteln ist nicht so 
abwägig, besonders in der kategorie "RESTRICTED",..

Da reichen simple graphic lbr'S aus um ein
>>INTRO
zu erzeugen,..
und man braucht keine 500Mhz und 3DHard Render engine,..
wie es z.B.
http://thomaspfeifer.net/
Da guckst du einfach unter AVR-Projekte -> Ansteuerung eines NOKIA 
LCD,..
Dort wird deutlich was man mit einem avr schickes machen kann,...
besonders dieses bild macht es deutlich:
http://thomaspfeifer.net/nokia_display_4.jpg
=> Demos als intro ist eine gute lösung

ansonsten (wie oben vlt. schon erwähnt) RLE codierung, oder bei 25 
frames/s alle 5 frame einen keyframe mit 5 bit abstand und der rest wird 
mit 3D interpoleration getätigt,..
is nur ne idee,..

grüüße
______________________________________________________________________ 
___
edit:
die 5 bit abstand sollten möglichst in abs. position inc. bzw. dec. um 
ein gut möglichstes ergebnis zu erhalten,...

von Obelix (Gast)


Lesenswert?

Evtl reichen für ein Intro auch 5 Bilder/s und als kopdierung animated 
GIF.

von Sebastian (Gast)


Lesenswert?

5 frames pro sekunde? Da kann man ja den Pixeln wortwörtlich 
hinterherschauen... Neenee wenn schon denn schon.
Anscheinend glaubt hier niemand dass man das so "einfach" 
hinbekommt?!?!?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.