Seite 1 von 1

QTimer oder sleep [gelöst]

Verfasst: 19. August 2008 01:36
von oberschlingel
Hallo,

ich möchte regelmäßig, z.B. 12 mal pro Sekunde, ein Bild vom Bildschirm aufzeichnen (mit QPixmap::grabWindow). Das ganze geschieht in einem eigenen Thread.

Denkt ihr es ist sinnvoller (genauer), die Aufnahmen mit einem QTimer auszulösen oder die Zeit zwischen den Aufnahmen mit einem msleep zu überbrücken? Und warum?

Wenn ich es richtig sehe, addieren sich ja die Fehler jeder Zeitmessung. Wenn ich also längere Zeit Bilder aufnehme, wird die Framerate ja immer ungenauer. Wie kann ich diesen Fehler also möglichst gering halten?

Tausend Dank für eure Antworten!

Verfasst: 19. August 2008 08:31
von CaptnChaos
Ich würde einen QTimer nutzen und so kritisch ist die abweichung auch nicht. ich glaub kaum das das jemand nachmisst.

Verfasst: 19. August 2008 08:35
von RHBaum
wenn du es wirklich genau brauchst (was ich ned wirklich glaub)...

in nem eigenen thread, und ned mit nem einfachen thread sondern selber ausrechnen wieviel nach dem letzen snapshot noch bis zum naechsten brauchst ....

Ciao ....

Re: QTimer oder sleep

Verfasst: 19. August 2008 08:45
von pfid
oberschlingel hat geschrieben:Wenn ich also längere Zeit Bilder aufnehme, wird die Framerate ja immer ungenauer.
Warum? Und was macht dein Thread, wenn er gerade nicht Bilder aufzeichnet?

Verfasst: 19. August 2008 11:40
von oberschlingel
Danke für eure Antworten.
Ein zweiter Thread zeichnet während der Snaphots vom Bildschirm auch noch Audiodaten auf. Diese sollen zeitlich synchron zu den Bilddaten gespeichert werden. Daher soll die Framerate möglichst stimmen, damit kein Versatz zwischen Bild und Ton entsteht.
Der Bildaufnahme-Thread macht zwischen den einzelnen Aufnahmen sonst gar nichts.

Meint ihr ein einfacher QTimer ist dafür ausreichend? Und was spricht gegen ein Sleep?

@RHBaum: Wie rechne ich die Zeit denn aus? Ist die Berechnung dann nicht genauso fehleranfällig wie ein QTimer (immerhin muss der Berechnungs-Thread ja genauso warten, wenn etwas anderes im Gang ist)?

DANKE

Verfasst: 19. August 2008 12:22
von pfid
oberschlingel hat geschrieben: Der Bildaufnahme-Thread macht zwischen den einzelnen Aufnahmen sonst gar nichts.
Und wie hast du das garnichts machen implementiert?

Verfasst: 19. August 2008 12:29
von oberschlingel
Derzeit mit einem Sleep. Der Bildaufnahme-Thread liest das Bild vom Bildschirm und schreibt es in einen QPixmap-Ringbuffer (als Array implementiert). Dann wartet er mit msleep X ms und macht das nächste Bild.
Ich frage mich eigentlich nur, ob ein QTimer besser geeignet wäre und ganz besonders warum.

Verfasst: 19. August 2008 13:32
von pfid
Ich würde dir ne QWaitCondition in der runloop empfehlen, die vom Audio-Thread aufgeweckt wird sobald das neue Bild ansteht, oder nach spätestens X ms.

Ich weiß nicht, wieviel Arbeit der Audio/Bilderthread zu verrichten hat, aber vielleicht wär es auch ne Alternative, das Bildspeichern in den Audiothread zu packen, und nach X ms auszuführen. So musst du die 2 Threads nicht synchroniniseren. Bei der Threadsynchronisation kannst du zwangsläufig mit Abweichungen durchs Scheduling rechnen, wie groß die sind hängt vom OS ab, in wie weit die sich abhängig von der Laufzeit des Videos auswirken, weiß ich nicht.

Einen QTimer würde ich nicht zur Threadsynchronisation verwenden. Mir ist im moment auch nicht klar, wie du das implementieren wolltest.

Verfasst: 19. August 2008 13:50
von RHBaum
@RHBaum: Wie rechne ich die Zeit denn aus? Ist die Berechnung dann nicht genauso fehleranfällig wie ein QTimer
Es ist ned genauer, du weisst halt nur dann was passiert ist ....

problem bei qtimer:

wenn deine eventloop blockiert ist (weil der mainthread grad was aufwendigeres tut / auf ne systemressource wartet) wird dein qtimer event ned mehr ausgefuehrt -> luecke

problem bei thread:
wenn irgend nen thread/prozess laeuft, wo das BS meint es haett ne hoehere prio -> bekommst weniger zeit zugeteilt -> schaffst es vielleicht nicht mehr in ein oder paar wenigen threadzyklen -> luecken ...
aber zumindest kann dich der mainthread deiner eigenen App nimmer so einfach blockieren

Mit den "zeiten messen" koenntest du nur rausbekommen, wie (un)genau du die rechzeit zugeteilt bekommst .... und ggf. darauf mit korrekturen reagieren. Normalerweisse sollte ein prog was sowas macht auch mit groesseren luecken zurechtkommen und dein sound dann z.b ned asynchron laufen zu beginnen ....

willst du alles haargenau, und feste zeitscheiben zu feste groesse der zugetielten rechenzeiten -> echtzeit BS /Erweiterung ..... (fuer deinen fall aber overkill)

Ciao ...

Verfasst: 19. August 2008 14:03
von oberschlingel
Danke für eure Antworten.

Derzeit läuft es so:

A. Ein hochpriorisierter Audiothread mit einer Callbackfunktion liest die Audiodaten von der Soundkarte und schreibt sie in einen Ringbuffer.

B. Ein hochpriorisierter Imagethread macht Abbilder vom Bildschirm und schreibt sie in einen Ringbuffer. Die Bilder werden mit einer festen Framerate erstellt. Hier wollte ich also sleep-Foto-sleep-Foto-sleep usw. verwenden oder eine eigene Eventloop, die von einem QTimer immer wieder gestartet wird.

C. Ein niedrigpriorisierter dritter Thread liest die Daten aus den zwei Ringbuffern und erstellt daraus ein Video (FLV-Format). Hierzu muss ich natürlich die Framerate der Bilder kennen, um sie mit den Audiodaten zu synchronisieren.

Das wars eigentlich. Nun habe ich drei Lösungsmöglichkeiten, um die Framerate des Imagethreads zu steuern:
1. Imagethread vom Audiothread regelmäßig wecken (Lösung von pfid)
2. Eine Schleife und msleep im Imagethread nutzen, um die Framerate dazustellen (derzeit so implementiert)
3. Ein eigener Eventloop, der von einem QTimer regelmäßig gestartet wird

Wozu würdet ihr tendieren?

DANKE

Verfasst: 19. August 2008 15:05
von RHBaum
wie waers wenn du die zeitstempel (QueryPerformanceCounter) mit abspeicherst und die zum synchronisieren nimmst ....
irgendwie musst doch bei nem videoformat auch die frameraten, bzw zeitstempel mit angeben, ansonsten gaebs ja nen zeitraffer effekt oder so ...

Ciao .....

Verfasst: 19. August 2008 15:35
von oberschlingel
Danke, daran habe ich gar nicht gedacht. Ich habe die Zeitstempel einfach entsprechend der Framerate berechnet.
Komme ich an so etwas wie Zeitstempel (z.B. in ms) auch ohne QueryPerformanceCounter? Denn das ist doch nur für Windows, richtig? Ich hätte es gern plattformübergreifend.

Noch eine Anmerkung: Derzeit, mit fester Framerate, berechnetem Zeitstempel und msleep funktioniert es ja alles gut. Ich habe es aber noch nicht auf einem langsamen PC getestet. Daher fragte ich mich nur grundsätzlich, ob ein QTimer besser (genauer) wäre als msleep und warum.

Verfasst: 19. August 2008 16:16
von RHBaum
QTimer waere genauer, wenn es nach durchlaufen der OnTimerevents den zeitstempel nimmt, und dann berechnet, wie lange es zum naechsten "gewuenschten" timerevent noch ist und dann dementsprechend lange wartet.
weiss ned ob das qtimer tut ....
dagegen spricht, das sobald dein mainthread blockiert wird, die qtimer events soweiso blockiert werden. also sobald irgendwas deine anwendung blockiert, du deine qtimer soweiso vergessen kannst. Imho wenig sinnvoll da viel energie zum einhalten der zeiten zu investieren ...

machs selber (eigener thread) und rechne selber mit den zeitstempeln.

ne plattformunabhaengige funktion gibts imho ned in genuegender genaueigkeit.
Aber QueryPerformancecounter liest eh nur das rtcflag vom prozessor aus, fuer linux hab ich schon codebeispiele gesehen die das auch machen ...
plattformunabhaengigkeit musst dann selber herstellen durch eigene kapslung mit compilerdirektiven ...

Ciao ...

Verfasst: 19. August 2008 17:13
von oberschlingel
Danke RHBaum!