QTimer oder sleep [gelöst]
-
oberschlingel
- Beiträge: 85
- Registriert: 11. April 2006 09:25
- Wohnort: Berlin
QTimer oder sleep [gelöst]
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!
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!
Zuletzt geändert von oberschlingel am 19. August 2008 17:14, insgesamt 1-mal geändert.
-
CaptnChaos
- Beiträge: 605
- Registriert: 28. Juni 2007 15:01
- Kontaktdaten:
Re: QTimer oder sleep
Warum? Und was macht dein Thread, wenn er gerade nicht Bilder aufzeichnet?oberschlingel hat geschrieben:Wenn ich also längere Zeit Bilder aufnehme, wird die Framerate ja immer ungenauer.
-
oberschlingel
- Beiträge: 85
- Registriert: 11. April 2006 09:25
- Wohnort: Berlin
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
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
-
oberschlingel
- Beiträge: 85
- Registriert: 11. April 2006 09:25
- Wohnort: Berlin
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.
Ich frage mich eigentlich nur, ob ein QTimer besser geeignet wäre und ganz besonders warum.
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.
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.
Es ist ned genauer, du weisst halt nur dann was passiert ist ....@RHBaum: Wie rechne ich die Zeit denn aus? Ist die Berechnung dann nicht genauso fehleranfällig wie ein QTimer
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 ...
-
oberschlingel
- Beiträge: 85
- Registriert: 11. April 2006 09:25
- Wohnort: Berlin
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
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
-
oberschlingel
- Beiträge: 85
- Registriert: 11. April 2006 09:25
- Wohnort: Berlin
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.
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.
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 ...
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 ...
-
oberschlingel
- Beiträge: 85
- Registriert: 11. April 2006 09:25
- Wohnort: Berlin