Underrun beim Befuellen des Demux erkennen?

Sklaventreiber
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

jw hat geschrieben: Aber wieso schreibt write() trotz O_NONBLOCK die Daten immer vollstaendig hinaus selbst wenn mehr als 1MByte uebergeben werden? Da muss doch irgendwo ein grosser Puffer existieren?
Das liegt daran, daß O_NONBLOCK gar nicht ausgewertet wird. 8)

Wenn du einen TS-Stream mit Ziel DECODER ins DVR-Device schreibst wird das, was du schreibst erst durch den swfilter geschoben und dann über die überschriebene write_to_decoder-Funktion direkt in die Demux-Video/Audiopuffer geschrieben, die momentan jeweils 64kByte groß sind (bei SPTS werden beide zusammen verwendet, daher ist es dann wie eine Queue mit 128kByte).

Von dort liest der Avia die Daten dann direkt per DMA in sein eigenes RAM. Es ist also immer ein blockierender write.
Ich bin davon ausgegangen, dass ich zum dekodieren DMX_OUT_DECODER nehmen muss. Ist das falsch? Was sind denn die genauen Unterschiede?
Naja, der Unterschied ist der Puffer, aus dem man das ganze lesen will. Ich sprach aber vom Lesen, nicht vom Schreiben.

Der generelle Weg beim Dekodieren ist:
FE -> Demux -> Decoder

Anstelle vom Hardware Frontend (FE) kann hier auch ein "RAM"-Frontend stehen. Und die DVBAPI ist flexibel genug, daß das auch funktioniert wenn man gar nicht wirklich in den Demux schreiben kann (wie bei der dbox2) und demultiplext dann den Strom in Software (bei TS-Wiedergabe natürlich nicht nötig).

Theoretisch kann man also TS-Daten ins DVR schreiben und anschließend dann über einen Filter wieder auslesen. :)
Hmm, wird da wirklich ein Restart ausgeloest? Durch was? Watchdog?
Ja, aber durch den in der Avia-Firmware. Der hat nichts mit den Watchdogs von derget zu tun.
Ich denke es wuerde Sinn machen write() einen Fehler melden zu lassen.


Dafür müßte man aber erstmal wissen, daß der Puffer auch tatsächlich leergelaufen ist.
jw
Interessierter
Interessierter
Beiträge: 56
Registriert: Dienstag 12. Juli 2005, 22:48

Beitrag von jw »

Npq hat geschrieben:
jw hat geschrieben: Aber wieso schreibt write() trotz O_NONBLOCK die Daten immer vollstaendig hinaus selbst wenn mehr als 1MByte uebergeben werden? Da muss doch irgendwo ein grosser Puffer existieren?
Das liegt daran, daß O_NONBLOCK gar nicht ausgewertet wird. 8)

Wenn du einen TS-Stream mit Ziel DECODER ins DVR-Device schreibst wird das, was du schreibst erst durch den swfilter geschoben und dann über die überschriebene write_to_decoder-Funktion direkt in die Demux-Video/Audiopuffer geschrieben, die momentan jeweils 64kByte groß sind (bei SPTS werden beide zusammen verwendet, daher ist es dann wie eine Queue mit 128kByte).
Das heisst, es macht garkeinen Sinn, mehr als 128KB-Bloecke zu schreiben? BTW: Muss ich den SPTS-Mode explizit aktivieren oder geht das automatisch? Muss mich dieser Mode ueberhaupt interessieren?
Von dort liest der Avia die Daten dann direkt per DMA in sein eigenes RAM. Es ist also immer ein blockierender write.
Ist avia_gt_dmx_queue_write() die Stelle, wo der Puffer beschrieben wird? Wenn ich diese Funktion richtig interpretiere, dann ist es sogar schaedlich, in grossen Bloecken zu schreiben, weil dann immer erst gewartet wird bis der Puffer ganz leer wird bevor der eigentliche Schreibvorgang passiert. Damit ist dann keine Reserve vorhanden, wenn der Scheduler mal die 10ms nicht einhalten sollte.
Ich bin davon ausgegangen, dass ich zum dekodieren DMX_OUT_DECODER nehmen muss. Ist das falsch? Was sind denn die genauen Unterschiede?
Naja, der Unterschied ist der Puffer, aus dem man das ganze lesen will. Ich sprach aber vom Lesen, nicht vom Schreiben.
Also ist DMX_OUT_DECODER doch richtig?
Theoretisch kann man also TS-Daten ins DVR schreiben und anschließend dann über einen Filter wieder auslesen. :)
Nunja, wenn es spass macht ;-) Ich will ja den Stream auf der Mattscheibe haben :)
Hmm, wird da wirklich ein Restart ausgeloest? Durch was? Watchdog?
Ja, aber durch den in der Avia-Firmware. Der hat nichts mit den Watchdogs von derget zu tun.
Das erklaert freilich, dass diese restarts nicht mit dmesg zu sehen sind... Waere es (zumindest theoretisch) moeglich, solche Restarts zu erkennen?
Ich denke es wuerde Sinn machen write() einen Fehler melden zu lassen.

Dafür müßte man aber erstmal wissen, daß der Puffer auch tatsächlich leergelaufen ist.
Hmmm, da stehe ich jetzt aber auf dem Schlauch. Gibt es ein prinzipielles Problem, das zu erkennen? Als erste Naeherung
waere es doch denkbar vor dem Schreiben den Fuellstand zu pruefen. Wenn der Puffer ganz leer ist, ist die Wahrscheinlichkeit hoch, dass er leergelaufen war.

BTW: beim Stoebern bin ich ueber eine Ungereimtheit in avia_gt_dmx_queue_irq() gestossen: Der Fall OW==R ist garnicht abgedeckt. Das ware doch dann der Fall, wenn der Lesezeiger den (alten) Schreibzeiger einholt. Mit anderen Worten also, wenn der Puffer leer gelaufen ist/war.
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

jw hat geschrieben:Das heisst, es macht garkeinen Sinn, mehr als 128KB-Bloecke zu schreiben? BTW: Muss ich den SPTS-Mode explizit aktivieren oder geht das automatisch? Muss mich dieser Mode ueberhaupt interessieren?
Stell dir den DVR einfach als Eingang zum Demux vor, in den du nun statt des Frontends den TS-Datenstrom schreibst. Daß es nicht wirklich durch den physikalischen Demux geht sollte eigentlich keine Auswirkungen auf die Benutzung haben.

DMX_OUT_DECODER heißt dann "sende die TS-Daten an den Dekoder". Von daher ist hier also der SPTS-Mode automatisch aktiviert. Alles andere würde auch eine Filterung (in Software) voraussetzen und ist daher nicht sinnvoll.

Der DualPES-Modus kann aber auch benutzt werden, dafür muß man direkt in den Video und Audio-Dekoder schreiben (ioctl VIDEO_SELECT_SOURCE auf VIDEO_SOURCE_MEMORY). Das funktionierte aber soweit ich mich erinnere noch nicht oder nicht zufriedenstellend (gagga hatte damit mal experimentiert). Dort funktioniert übrigens auch der nicht-blockierende write().
jw hat geschrieben:Damit ist dann keine Reserve vorhanden, wenn der Scheduler mal die 10ms nicht einhalten sollte.
Es wird in der while-Schleife solange geprüft, bis entweder die Queue genug Platz hat oder sie ganz leer ist (wenn das zu Schreibende größer ist als die Queue). Der schedule-Aufruf soll dafür dienen, daß nicht das ganze System blockiert wird. Theoretisch wäre es natürlich besser, man müßte diese Information nicht alle 10ms pollen, daher sicherlich auch das "optimize" an der Stelle.
jw hat geschrieben: Als erste Naeherung waere es doch denkbar vor dem Schreiben den Fuellstand zu pruefen. Wenn der Puffer ganz leer ist, ist die Wahrscheinlichkeit hoch, dass er leergelaufen war.
Das Problem ist, daß der Füllstand beim Schreiben der Füllstand der Demux-Queue ist und nicht der - hier entscheidende - Füllstand des Avia-Dekoders. Da die Daten vom Avia selbst gelesen werden gibt es keine Routine, die prüfen könnte.

Man kann den Füllstand des Video-Puffers auslesen, dies ist aber nur ein momentaner Zustand und kann sich im nächsten Moment schon wieder ändern.

Ich habe aber festgestellt, daß der Avia einen Buffer underrun korrekt meldet. Meine Bedenken waren, daß diese Meldung eventuell nicht käme. Das scheint aber so zu sein wie man aus den Debug-Ausgaben erkennt.

Der Dekoder scheint übrigens entgegen meiner Vermutung dann auch keinen Restart durchzuführen, sondern einfach nur die Daten anzunehmen und nichts mehr zu tun. Das ist auch die Ursache für den "Blackscreen"-Bug, zumindest bei mir. Die Puffer werden gefüllt und transferiert, aber der Dekoder legt nicht mehr los.

Muß man nochmal genauer evaluieren, habe dafür aber gerade keine Zeit.
jw hat geschrieben:BTW: beim Stoebern bin ich ueber eine Ungereimtheit in avia_gt_dmx_queue_irq() gestossen: Der Fall OW==R ist garnicht abgedeckt. Das ware doch dann der Fall, wenn der Lesezeiger den (alten) Schreibzeiger einholt. Mit anderen Worten also, wenn der Puffer leer gelaufen ist/war.
Das wäre ja in Ordnung, da ein read ja ruhig alle Daten lesen darf, die vorhanden sind. Der Lesezeiger dort betrifft nur die Daten, die (per Software) in den Speicher kopiert werden (Sections, Streamdaten)

Die Analyse geht darum, einen Overflow zu erkennen. Wenn z.B. die Daten nicht schnell genug gelesen werden, dann überschreibt der Demux die noch nicht ausgelesenen Daten (weil das per DMA passiert). In diesem Falle kann man aus der Position des Lesezeigers erkennen, ob dies passiert ist oder nicht.
jw
Interessierter
Interessierter
Beiträge: 56
Registriert: Dienstag 12. Juli 2005, 22:48

Beitrag von jw »

[ Im Vorposting ist wohl das Quoting etwas durcheinandergeraten. Ich versuche das mal zu korrigieren. ]
Npq hat geschrieben:
jw hat geschrieben:Das heisst, es macht garkeinen Sinn, mehr als 128KB-Bloecke zu schreiben? BTW: Muss ich den SPTS-Mode explizit aktivieren oder geht das automatisch? Muss mich dieser Mode ueberhaupt interessieren?
Stell dir den DVR einfach als Eingang zum Demux vor, in den du nun statt des Frontends den TS-Datenstrom schreibst. Daß es nicht wirklich durch den physikalischen Demux geht sollte eigentlich keine Auswirkungen auf die Benutzung haben. DMX_OUT_DECODER heißt dann "sende die TS-Daten an den Dekoder". Von daher ist hier also der SPTS-Mode automatisch aktiviert. Alles andere würde auch eine Filterung (in Software) voraussetzen und ist daher nicht sinnvoll.
Das hatte ich bislang auch so verstanden. Aber die wiederkehrenden Verweise auf SPTS-, Clip- und sonstige Modes hatten mich verwirrt :roll:. Deshalb auch meine Frage, ob mich dieser Mode ueberhaupt interessieren muss ;-)
jw hat geschrieben:Damit ist dann keine Reserve vorhanden, wenn der Scheduler mal die 10ms nicht einhalten sollte.
Es wird in der while-Schleife solange geprüft, bis entweder die Queue genug Platz hat oder sie ganz leer ist (wenn das zu Schreibende größer ist als die Queue).
Wenn ich aber nun in Bloecken von 1MBytes schreibe, dann wartet er _immer_ darauf, dass der Puffer _komplett_ leer wird, bevor _irgendwas_ geschrieben wird. IMHO waere es guenstiger, vor dem schedule-Aufruf wenistens soviel zu schreiben, wie zu diesem Zeitpunkt reinpasst. Und genau das besagt ja IMHO auch die FIXME-Notiz.
jw hat geschrieben: Als erste Naeherung waere es doch denkbar vor dem Schreiben den Fuellstand zu pruefen. Wenn der Puffer ganz leer ist, ist die Wahrscheinlichkeit hoch, dass er leergelaufen war.
Das Problem ist, daß der Füllstand beim Schreiben der Füllstand der Demux-Queue ist und nicht der - hier entscheidende - Füllstand des Avia-Dekoders. Da die Daten vom Avia selbst gelesen werden gibt es keine Routine, die prüfen könnte.
Ist das denn nicht der gleiche Puffer, nur dass der Avia per DMA darauf zugreift? Die Avia-Zeiger werden doch in hw_write_pos/hw_read_pos gespiegelt und sind damit dann auch beim Beschreiben des Puffers sichtbar (bzw koennen mittels avia_gt_dmx_queue_get_write_pos() ermittelt werden), oder nicht?
Man kann den Füllstand des Video-Puffers auslesen,
Das ist dann aber wieder ein andere Puffer?
dies ist aber nur ein momentaner Zustand und kann sich im nächsten Moment schon wieder ändern.
Dass das nur ein momentaner Zustand ist, ist schon klar. Aber wenn der Fuellstand null ist, waere es IMHO vorteilhaft, vorsorglich neu aufzusetzen, auch wenn es (noch) nicht zu Fehlern gekommen ist. Der Effekt der eintritt, wenn der Avia stolpert (fehlerhafte Wiedergabe bis hin zum Absturz, so dass ein power-cycle notwendig wird) ist IMHO viel aergerlicher als ein (vorsorgliches) neu aufsetzen.
Ich habe aber festgestellt, daß der Avia einen Buffer underrun korrekt meldet. Meine Bedenken waren, daß diese Meldung eventuell nicht käme. Das scheint aber so zu sein wie man aus den Debug-Ausgaben erkennt.
Hmm, ich weiss nicht... Das einzige, was bei mir kommt ist:

Code: Alles auswählen

SPTS, queue 0 extended.
avia_av_wdt_thread: video decoding stopped ==> restart
SPTS, queue 0 extended.
avia_av_wdt_thread: video decoding stopped ==> restart
avia_av_wdt_thread: video decoding stopped ==> restart
SPTS, queue 0 extended.
avia_av_wdt_thread: video decoding stopped ==> restart
SPTS, queue 0 extended.
SPTS, queue 0 extended.
Aber das kommt allerhoechstens in 5% der Faelle. Im Normalfall kommt garkeine Meldung. Deswegen glaube ich nicht dass diese Meldungen mit dem Underrun zusammenhaengen...
Der Dekoder scheint übrigens entgegen meiner Vermutung dann auch keinen Restart durchzuführen, sondern einfach nur die Daten anzunehmen und nichts mehr zu tun. Das ist auch die Ursache für den "Blackscreen"-Bug, zumindest bei mir.
Schwarzer Bildschirm und nur bruchstueckhafte Audio-Fetzen? Ja, das habe ich auch, wenn der genannte Puffer-Unterlauf fuer laengere Zeit anhaelt. Tritt das ein, ist auf jeden Fall ein Power-Cycle noetig.
Die Puffer werden gefüllt und transferiert, aber der Dekoder legt nicht mehr los. Muß man nochmal genauer evaluieren, habe dafür aber gerade keine Zeit.
jw hat geschrieben:BTW: beim Stoebern bin ich ueber eine Ungereimtheit in avia_gt_dmx_queue_irq() gestossen: Der Fall OW==R ist garnicht abgedeckt. Das ware doch dann der Fall, wenn der Lesezeiger den (alten) Schreibzeiger einholt. Mit anderen Worten also, wenn der Puffer leer gelaufen ist/war.
Das wäre ja in Ordnung, da ein read nicht mehr Daten lesen kann als vorhanden sind.
Ist schon klar. Ich meinte vielmehr, dass man das als Indiz fuer einen Puffer-Unterlauf nehmen koennte.
Der Lesezeiger dort betrifft nur die Daten, die in den Speicher kopiert werden (Sections, Streamdaten)
Also Daten, die vom FE kommen? Das waere dann eine andere Baustelle.
Die Analyse geht darum, einen Overflow zu erkennen. Wenn z.B. die Daten nicht schnell genug gelesen werden, dann überschreibt der Demux die noch nicht ausgelesenen Daten (weil das per DMA passiert). In diesem Falle kann man aus der Position des Lesezeigers erkennen, ob dies passiert ist oder nicht.
Ich meinte, dass man diesen Fall (OW==R) als Indiz fuer einen _Unterlauf_ nehmen koennte.

Danke nochmal fuer die Ausfuehrlichen Erlaeuterungen.
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

jw hat geschrieben:Aber die wiederkehrenden Verweise auf SPTS-, Clip- und sonstige Modes hatten mich verwirrt :roll:. Deshalb auch meine Frage, ob mich dieser Mode ueberhaupt interessieren muss ;-)
Nein, die "Problematik" mit den Modes existiert nur, weil man im DualPES-Modus die gerade dekodierten Video/Audio-Daten nicht mehr als TS streamen kann, sondern nur als PES (weil der Demux den TS nur einmal filtern kann, neuere Demuxer, z.B. der in der TripleDragon haben mehrere Demuxeinheiten, bei diesen ist es möglich, gleichzeitig PES und TS zu streamen).

Im Grunde braucht einen der Dekodier-Modus nur dann zu interessieren, wenn man die Daten, die gerade dekodiert werden mitschneiden möchte.
jw hat geschrieben:Wenn ich aber nun in Bloecken von 1MBytes schreibe, dann wartet er _immer_ darauf, dass der Puffer _komplett_ leer wird, bevor _irgendwas_ geschrieben wird. IMHO waere es guenstiger, vor dem schedule-Aufruf wenistens soviel zu schreiben, wie zu diesem Zeitpunkt reinpasst. Und genau das besagt ja IMHO auch die FIXME-Notiz.
Das gilt aber nur, wenn die Menge an Daten, die geschrieben werden soll (count) größer ist als der Queue-Puffer. Ansonsten wird gewartet bis die Menge an Daten frei ist, die geschrieben werden soll. Aber es ist schon richtig, daß einem die Logik sagt, daß man soviel schreiben soll wie hineinpaßt. Warum das so angelegt wurde kann ich dir nicht sagen, man müßte mal probieren, ob das Schreiben von kleinen Datenmengen evtl. Probleme bereitet (wir schreiben hier ja in das Demux-RAM).

Allerdings darf man nicht vergessen, daß hier nicht die gesamten 1 MiByte geschrieben werden, sondern nur jeweils ein TS-Paket, also 188 Bytes.
jw hat geschrieben:Ist das denn nicht der gleiche Puffer, nur dass der Avia per DMA darauf zugreift? Die Avia-Zeiger werden doch in hw_write_pos/hw_read_pos gespiegelt und sind damit dann auch beim Beschreiben des Puffers sichtbar (bzw koennen mittels avia_gt_dmx_queue_get_write_pos() ermittelt werden), oder nicht?
Nein, das ist nur das Demux-RAM. Der Avia-Videopuffer liegt im Avia-RAM. Das sind zwei getrennte RAM-Bausteine und auch unabhängig vom Hauptspeicher der Box.

Es gibt allerdings auch nicht wirklich eine Anzeige des Füllstands, sondern nur eine Anzeige, wie viel Platz noch vorhanden ist "Emptiness". Läuft der Puffer leer, so bleibt dieser Wert auf Maximum und der "BUF_UND"-Interrupt wird ausgelöst.

Leider wird das alles von der Firmware im Avia ausgelöst und diese verwaltet auch sämtliche Parameter wie die Puffergröße, so daß man nicht mit Sicherheit sagen kann was da intern genau passiert.

Für mich wäre es sehr spannend, die Firmware mal auseinanderzunehmen, aber das ist nicht nur eine RISC-CPU wie beim Demux, sondern da steckt auch noch Hardware für die Dekodierung mit drin (IDCT). Dazu kommt noch, daß das alles natürlich undokumentiert ist, was zwar den Reiz stark erhöht aber auch den Aufwand. :)

Die Debugmeldungen von denen ich sprach gibt der Treiber im CVS nicht aus. Es handelt sich dabei um den besagten "BUF_UND"-Interrupt, den ich einfach mal mit einem printk versehen habe. Darauf könnte man reagieren und den Dekoder neu anwerfen falls er im Play-Zustand ist.

Schön wäre natürlich wenn dieser Zustand nie eintreten würde.
jw hat geschrieben:Ich meinte, dass man diesen Fall (OW==R) als Indiz fuer einen _Unterlauf_ nehmen koennte.
Dann wüßtest du wie beschrieben nur, daß der Demux-Puffer leer ist, was ja durchaus OK ist, der Avia-Puffer kann ja gleichzeitig noch gefüllt sein (wird ja weitergereicht).