Rückgabewert von cDevice::Poll wird ignoriert

  • Dies ist die Fortsetzung von
    Sinn und Unsinn von "emergency exit"


    Mich stört schon länger, daß DevicePoll(Poller, 10); in dvbplayer.c den Rückgabewert ignoriert.
    Ein Fehler ist es nicht, da ich schon einen Workaround verwende.


    Ich habe extrem große Ausgabepuffer von bis zu 8s.


    cDevice::Poll liefert false (busy/voll) zurück sobald meine Devicepuffer genügend gefüllt wird.
    Da aber der Rückgabewert nie überprüft wird, wird weiter cDevice::PlayVideo, ... aufgerufen.
    Und die Puffer komplett gefüllt.


    Ich habe mir dadurch geholfen, daß ich in meinem cDevice::PlayVideo cDevice::PlayAudio
    noch einmal prüfe ob für beides genug Daten vorhanden sind und dann weiter Pakete
    ablehne.


    Wenn ich mich richtig errinnere war das Problem, daß die Daten in den Puffern bei
    Sprüngen und Richtungswechseln zu Fehlern führte.


    Johns

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

  • Dies ist die Fortsetzung von
    Sinn und Unsinn von "emergency exit"


    Mich stört schon länger, daß DevicePoll(Poller, 10); in dvbplayer.c den Rückgabewert ignoriert.
    Ein Fehler ist es nicht, da ich schon einen Workaround verwende.


    Ich würde das nicht als "Workaround" bezeichnen, sondern als die richtige Implementierung (siehe unten).
    Ein Ausgabedevice darf nicht zwingend voraussetzen, daß der Player jemals Poll() aufruft. Ein Player könnte ohne weiteres ständig PlayTs() aufrufen, und das Ausgabedevice liefert halt 0 zurück, wenn sein Puffer voll ist. Wenn der Player nicht zu "busy" werden will, dann kann er Poll aufrufen um Zeitscheiben an andere Threads abzugeben. Er ist aber in keinster Weise verpflichtet, den Rückgabewert des Poll-Aufrufes auszuwerten.


    Quote


    Ich habe extrem große Ausgabepuffer von bis zu 8s.


    Wieso eigentlich? Hat das einen konkreten Grund, daß die Puffer dermaßen groß sind?


    Quote


    cDevice::Poll liefert false (busy/voll) zurück sobald meine Devicepuffer genügend gefüllt wird.
    Da aber der Rückgabewert nie überprüft wird, wird weiter cDevice::PlayVideo, ... aufgerufen.
    Und die Puffer komplett gefüllt.


    Was ist denn daran falsch, die Puffer komplett gefüllt zu halten?


    Quote


    Ich habe mir dadurch geholfen, daß ich in meinem cDevice::PlayVideo cDevice::PlayAudio
    noch einmal prüfe ob für beides genug Daten vorhanden sind und dann weiter Pakete
    ablehne.


    Das ist ja auch dein gutes Recht ;)


    Der Aufruf von DevicePoll(Poller, 10) in cDvbPlayer::Action() dient ja nur dazu, daß die Schleife nicht zu "busy" wird, und jederzeit weitermachen kann, sobald der Ausgabepuffer Daten annehmen kann. Aus der Sicht des Players müsste es sogar erlaubt sein, ständig PlayTs() aufzurufen ohne jemals einen Poll zu machen, denn PlayTs() darf nicht "blockieren".


    Quote


    Wenn ich mich richtig errinnere war das Problem, daß die Daten in den Puffern bei
    Sprüngen und Richtungswechseln zu Fehlern führte.


    Das verstehe ich nicht ganz. Bei Sprüngen und Richtungswechseln werden doch über DeviceClear() die Puffer gelöscht!?


    Klaus


  • Wieso eigentlich? Hat das einen konkreten Grund, daß die Puffer dermaßen groß sind?


    Faulheit.


    Zwischen dem Audio und Video Stream gibt es Teilweise sehr große Zeitabstände.
    Die Zeitstempel für den Ton liegen teilweise bis 1.4s vor dem Bild.
    Habe mich gewundert, aber dvbsnoop zeigt ein ähnlches Bild.
    Dann brauche ich einen Tonpuffer von min 0.3s um Tonaussetzer zu vermeiden.


    Da die Puffer für den Worst Case 8 Kanal bzw. HDTV ausgelegt sind, kommen
    dann bei Stereo und SDTV noch größere Zeiten heraus.


    Quote


    Was ist denn daran falsch, die Puffer komplett gefüllt zu halten?


    Es entstehen Belastungspeaks beim ersten Befüllen der Puffer.
    Was beim Start oder Sprüngen passiert, hier ist das System durch die
    Dekoder auch besonders belastet.


    Quote


    Das verstehe ich nicht ganz. Bei Sprüngen und Richtungswechseln werden doch über DeviceClear() die Puffer gelöscht!?


    Es ist jetzt über ein Jahr her, daß ich diesen Teil geschrieben habe. Ich muß nochmal genau gucken was passiert.
    Ich glaube der Player meint er hätte die ~8s bereits gespielt und überspringt so die Daten die bereits im Puffer sind.
    Durch den Clear werden die ja verworfen. Aber dies ist jetzt nur rumraten, ich werde die Puffer noch etwas erhöhen
    und meine Softlimits entfernen.


    Johns

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

  • So ich habe mir das Problem noch einmal angeschaut.


    So wie es aussieht ist nur die Fortschrittsanzeige falsch.
    Wenn man vom normalen Abspielen auf schnellen Rücklauf umschaltet,
    es geht auch Zeitlupe rückwärts. Springt die Anzeige ein paar Sekunden
    zurück, dann läuft die Anzeige ein paar Schritte nach rechts um dann wieder
    zurückzuspringen und dann endlich richtig nach links zulaufen.


    Meine Puffer werden richtig gelöscht und das Ausgabedevice mit den richtigen
    Paketen gefüttert (Zeitstempel). Bis auf 1-2 noch alten Frames werden dann
    die neuen Frames mit den richtigen Zeitstempel angezeigt.


    Anbei ein Patch der das Softlimit im SoftHdDevice Plugin ausschaltet, bitte testen ob es Probleme
    beim Spulen usw. macht.


    Johns

    Files

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

  • Es grenzt an Leichenfledderei, diesen Thread nach über 11 Jahren nochmal aufzuwärmen, aber so brauche ich zumindest die Thematik nicht nochmal neu erläutern.

    Ich hätte dazu einige Fragen und hoffe hier insbesondere auf Erleuchtung durch kls :)

    Ist das heute unverändert so, dass der dvbplayer im vdr den Rückgabewert von


    Code
      virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
           ///< Returns true if the device itself or any of the file handles in
           ///< Poller is ready for further action.
           ///< If TimeoutMs is not zero, the device will wait up to the given number
           ///< of milliseconds before returning in case it can't accept any data.

    ignoriert?


    Was ist, wenn ein Ausgabedevice während der Wiedergabe einer Aufzeichnung in den Funktionen PlayVideo oder Play*Audio 0 returniert, weil seine buffer einen definierten Maximalfüllstand erreicht haben und es signalisieren möchte, dass es keine weiteren Daten annehmen kann? Ist dafür 0 überhaupt richtig, oder sollte -1 returniert werden? Die Beschreibung in device.h ist da nicht ganz eindeutig

    Code
    ...shall process the packet either as a whole (returning
           ///< Length) or not at all (returning 0 or -1 and setting 'errno' accordingly).
           ///< Returns the number of bytes actually taken from Data, or -1
           ///< in case of an error.

    Welchen Unterschied macht es aus Sicht von vdr, welchen Wert die Funktion des Ausgabedevice zurückgibt? Ändert das etwas am weiteren Schicken von Paketen? So wie ich die Aussage

    Quote

    . Aus der Sicht des Players müsste es sogar erlaubt sein, ständig PlayTs() aufzurufen ohne jemals einen Poll zu machen, denn PlayTs() darf nicht "blockieren".

    verstehe, ist das nicht der Fall. Haben denn die Rückgabewerte 0 und/oder -1 irgendwelche Folgen (z.B. Aufruf von Clear oder emergency exit)?


    Ich versuche derzeit ein Problem in softhdodroid zu analysieren. Während einer laufenden Zeitlupe versiegen nach einigen Sekunden die Videodaten - vdr ruft PlayVideo nicht mehr auf. Auf der Videoseite finde ich dafür keine Ursache. An Poll kann es nicht liegen, das scheint tatsächlich ignoriert zu werden, denn es wird noch eine ganze Zeitlang, nachdem Poll 0 (false) zurückliefert, immer noch PlayVideo aufgerufen. Die Buffer laufen weder über noch fordert vdr ein Clear an. Kann es sein, dass vdr die Lieferung von Videodaten stoppt, weil das Ausgabeplugin in Play*Audio 0 zurückgibt? (weil es während der Trickfunktionen so über Mute() die Tonausgabe unterdrückt)

    VDR1: ACT-620, Asus P8B75-M LX, Intel Core i3-3240, 4 GB DDR3 RAM 1600 MHz, passive Geforce GT1030 von MSI, Sandisk 2TB SSD, 2xWinTV DualHD, Atric-IR-Einschalter. SW: Xubuntu 20.04 auf 64GB Sandisk SSD.

    VDR2: Odroid N2+ mit CoreELEC und Ubuntu in chroot, WinTV DualHD

    VDR3: Tanix TX3 mit CoreELEC und Ubuntu in chroot, WinTV DualHD

  • Ist das heute unverändert so, dass der dvbplayer im vdr den Rückgabewert von Poll() ignoriert?

    Offensichtlich:

    Code
            else if (Sleep) {
               cPoller Poller;
               DevicePoll(Poller, 10);
               Sleep = false;
               if (playMode == pmStill || playMode == pmPause)
                  cCondWait::SleepMs(3);
               }

    Was ist, wenn ein Ausgabedevice während der Wiedergabe einer Aufzeichnung in den Funktionen PlayVideo oder Play*Audio 0 returniert, weil seine buffer einen definierten Maximalfüllstand erreicht haben und es signalisieren möchte, dass es keine weiteren Daten annehmen kann?

    Wenn es momentan keine weiteren Daten annehmen kann, soll es 0 zurückliefern. Wenn ein Fehler aufgetreten ist, der den weiteren Ablauf verhindert, dann -1.

    Welchen Unterschied macht es aus Sicht von vdr, welchen Wert die Funktion des Ausgabedevice zurückgibt?

    Du meinst die Poll-Funktion, oder? Keinen (da ja der Returnwert ignoriert wird). Das Polling dient dazu, weitermachen zu können, sobald das Device dazu in der Lage ist - und nicht unnötig zu warten.

    Haben denn die Rückgabewerte 0 und/oder -1 irgendwelche Folgen

    Hier meinst du die Play-Funktionen, oder? Das ist anscheinend nicht wirklich konsequent durchgezogen für negative Werte. So wie's aussieht funktionieren nur Werte >=0 richtig. Bei der Wiedergabe wird hier anscheinend kein Fehler erwartet ;-).

    Kann es sein, dass vdr die Lieferung von Videodaten stoppt, weil das Ausgabeplugin in Play*Audio 0 zurückgibt? (weil es während der Trickfunktionen so über Mute() die Tonausgabe unterdrückt)

    Halte ich für wahrscheinlich. Play*Audio() MUSS die Daten annehmen. Es kann sie im Mute-Fall gerne verwerfen, aber zunächst MUSS sie sie annehmen, sonst passiert genau das, was du beobachtest. Wobei, soweit ich das sehe, bei Zeitlupe gar keine Audiodaten an das Device geschickt werden:

    Code
                        if (!VideoOnly || HasIBPTrickSpeed()) {
                           int w = PlayTsAudio(Data, TS_SIZE);
                           if (w < 0)
                              return Played ? Played : w;
                           if (w == 0)
                              break;
                           Audios.PlayTsAudio(Data, TS_SIZE);
                           }
                        }

    Hast du evtl. cDevice::PlayTs() reimplementiert?

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!