[iptv] m3u, stream, radio Erweiterung

  • Ich habe mit UDP keinerlei möglichkeiten zu sehen ob der Empfänger die Daten angenommen hat oder nicht. Und wenn ich auf dauer leicht zu schnell sende dann laufen dort die Puffer voll und es gehen Daten verloren.

    Genau das sehe ich derzeit und es gibt Bildfehler.

    Warten wir mal ab war Zabrimus dazu sagt ob eine TCP Verbindung machen will.

  • Egal was ich tue ich bekomme es nicht hin den Stream konstant zu halten. Entweder die Puffer im IPTV Plugin incl. der Puffer im Ausgabeplugin laufen langsam voll oder sie laufen langsam leer.

    Das hatte ich bei meinen Versuchen im letzten Sommer auch bemerkt. Bei mir war es typischer weise ein Buffer-Underrun.

    Das erhöhen der Empfangspuffer auf der Schnittstelle brachte etwas Besserung.
    Ein größerer Sendepuffer brachte aber wenig bis nichts.

    Der Logik nach, sollte der Fall aber eigentlich gar nicht auftreten können.
    Da der Sender die Datenrate vorgibt, muss der Empfänger sich zwangsläufig darauf synchronisieren. (Nicht anders als bei Empfang via DVB generell.)
    Meine Vermutung ist, dass da irgendwas im Plugin nicht passt, was mal mehr und mal weniger auffällt.
    Unter Umständen ist es lediglich eine zu große Blockgröße, mit der die Daten auf die Schnittstelle geschrieben werden, was das Plugin außer tritt bringt.

    Das Faszinierende bei meinen Tests war, dass es mit ffmpeg als Quelle und xine als Client fehlerfrei über Stunden lief.

    Mein letzter Verdacht lag beim Ringbuffer vom VDR, den das Plugin auch verwendet.
    Da einige Timing Einstellungen, die ich mir mal ansehen wollte.
    Bei dem Stand musste ich aber leider abbrechen, da kamen dann andere Baustellen, die Vorrang haben. Seit dem ist meine Zeit für Hobbys leider erst mal extrem begrenzt.


    Die Parameter wären 1 Video-URL (samt VPID), 3 Audio-URL (samt 3 APID), die TSID, SID, Name des Kanals. Es kann aber auch nur eine URL sein, oder eine Video- und 1 oder 2 Audio-URL.

    Das alles als Parameter in einem Script, das die verschiedenen Möglichkeiten berücksichtigen muss, halte ich für nur schwer lesbar.

    Ich weiß nicht, ob die Fragestellung noch relevant ist, bin nur zufällig beim Überfliegen darüber gestolpert. Ggf. die Antwort einfach ignorieren.

    Für ein Bash-Skript würde ich das als eine Wortliste übergeben, getrennt mit einem Zeichen, was in einer URL nicht vorkommen darf (zB.";"). (Das spart einem das Quoting.)
    Die Wortliste ist nur ein Parameter und lässt sich im Skript elegant mit einer for-Schleife abarbeiten.

    Da es nur eine Video-URL gibt, ist die Zuordnung auch Problemlos, wenn man sich an eine Reihenfolge hält.

    Die PIDs muss man eigentlich gar nicht übertragen, da man sie frei wählen kann.
    Wenn man immer das gleiche Schema verwendet (zB. ab 100 hoch zählen) sollte das klappen.

    Oder man übergibt die Zeile aus der channels.conf als Parameter.
    Bei meinen Skripten hatte ich mir die Zeile via svdrp geholt, das hat auch geklappt.

    Ich hatte leider nicht die Zeit das hier detaillierter zu verfolgen und dachte die UDP-Schnittstelle und externe Skripte wären dank dieser Entwicklung obsolet. Da das aber anscheinend nicht der Fall ist, werde ich mal schauen, ob ich meine Basteleien soweit sortiert bekomme, dass ich sie im anderen Thread anhängen mag.

    Gruss
    SHF

    Mein (neuer) VDR:

    Software:
    Debian Wheezy mit Kernel 3.14
    VDR 2.0.7 & div. Plugins aus YaVDR-Paketen
    noad 0.8.6

    Hardware:
    MSI C847MS-E33, onboard 2x1,1GHz Sandybridge Celeron 847, 4GiB RAM
    32GB SSD (System), 4TB 3,5" WD-Red HDD (Video)
    TT FF DVB-S 1.5 FullTS-Mod PWM-Vreg-Mod, DVB-Sky 852 Dual DVB-S2
    Das ganze im alten HP Vectra VLi8-Gehäuse versorgt von:
    PicoPSU-160-XT und Meanwell EPP-150 im ATX-NT-Gehäuse

  • Der Logik nach, sollte der Fall aber eigentlich gar nicht auftreten können.
    Da der Sender die Datenrate vorgibt, muss der Empfänger sich zwangsläufig darauf synchronisieren.

    Im Prinzip ist das wohl so, aber nur bei Livestreams. Allerdings ist das extrem stark entkoppelt. Bei einem dash Stream werden Video und Audio in getrennten Dateien und unterschiedlicher Stückelung und Größe geliefert. Da gibt es keine konstante Datenrate.

    Das einzige was hier wirklich hilft ist ein durchgängiger Puffer bis ins Ausgabeplugin der einfach blockiert wenn er vollgelaufen ist. Dann werden keine weiteren Streamingdateien gelesen bis wieder Platz im Puffer ist. Und wenn dazwischen jemand ist der einfach nur in den Wald ruft, dann klappt das nicht :) Deswegen brauche ich eine TCP Verbindung die blockieren kann und darf.

  • Ich weiß nicht, ob die Fragestellung noch relevant ist, bin nur zufällig beim Überfliegen darüber gestolpert. Ggf. die Antwort einfach ignorieren.

    Das Problem habe ich jetzt ganz anders gelöst. In Beitrag #155 ist beschrieben, wie man jetzt zusätzlich zu vlc, ffmpeg auch ein Python Script aufrufen lassen kann, daß die Kommandozeile zurückgibt, die verwendet werden soll.

    Das beigelegte Script kann entweder verändert werden, komplett neu geschrieben oder wie es einem beliebt. Ich hoffe, damit alle Möglichkeiten abzudecken.

  • Im Prinzip ist das wohl so, aber nur bei Livestreams.

    Ich hatte immer mit den Live-Streams der Öffentlich-Rechtlichen getestet, daher beziehen sich meine Aussagen auch nur darauf.

    Da gibt es keine konstante Datenrate.

    Die Frame-Rate sollte aber normalerweise konstant sein.
    Damit sollten die Daten auch zeitnah in brauchbaren Häppchen eintrudeln.
    Im Prinzip wie bei DVB, unter Umständen aber in anderen Blockgrößen.

    Bis ffmpeg klappte es bei meinen Tests auch einwandfrei.
    Und was bei ffmpeg als UDP-Strom raus kam, spielte xine direkt auch einwandfrei ab.
    Daher mein Schluss, dass es nicht an ffmpeg und auch nicht an der UDP-Schnittstelle liegt.

    Das einzige was hier wirklich hilft ist ein durchgängiger Puffer bis ins Ausgabeplugin der einfach blockiert wenn er vollgelaufen ist.

    Bei mir sind die Puffer immer leer gelaufen und mir ist völlig unklar, warum das passiert.
    Zu Übertragungsverlusten sollte es nicht kommen, die Pakete verlassen den Computer ja nie. Von daher sollte auch UDP zuverlässig funktionieren.


    Was an Daten kommt bestimmt ffmpeg, da muss sich das Plugin halt anpassen.
    Das Plugin sollten den (recht kleinen) Empfangspuffer der Schnittstelle schnellst möglich leeren und die Daten intern puffern. (Und soweit ich das beurteilen kann wird das auch so gemacht.) Dass der Empfangspuffer der Schnittstelle leer läuft ist also normal und gewollt.
    Für mich sieht es daher danach aus, als ob das Plugin zu wenig puffert oder zu schnell lesen will.

    Sofern ich das richtig interpretiert habe, bin ich auch nie über ein paar wenige Prozent (<5%) Füllstand im Ringbuffer im Plugin gekommen. Irgendwie erscheint mir das doch recht knapp.
    Ein Ziel-Füllstand von 20-30% würde mir sinnvoll erscheinen.
    Beim Ringbuffer gibt es noch Einstellmöglichkeiten, die habe ich mir aber noch nicht näher angesehen.
    Wie die ganze Regelung abläuft überblicke ich aber noch nicht. Bei dem Thema habe ich bislang auch nur eher nur an der Oberfläche gekratzt.


    Unter Umständen läuft dadurch auch nur der Audio oder Video-Puffer leer, wenn die Blockgröße zu groß ist.
    Die Blockgröße kann man bei ffmpeg auch beeinflussen, das ist auch in einigen der Skripte drin. Da ist die Blockgröße eher groß eingestellt.
    Die Blockgröße testweise mal zu verringern, habe ich aus Zeitgründen aber noch nicht versucht.

    Gruss
    SHF

    Mein (neuer) VDR:

    Software:
    Debian Wheezy mit Kernel 3.14
    VDR 2.0.7 & div. Plugins aus YaVDR-Paketen
    noad 0.8.6

    Hardware:
    MSI C847MS-E33, onboard 2x1,1GHz Sandybridge Celeron 847, 4GiB RAM
    32GB SSD (System), 4TB 3,5" WD-Red HDD (Video)
    TT FF DVB-S 1.5 FullTS-Mod PWM-Vreg-Mod, DVB-Sky 852 Dual DVB-S2
    Das ganze im alten HP Vectra VLi8-Gehäuse versorgt von:
    PicoPSU-160-XT und Meanwell EPP-150 im ATX-NT-Gehäuse

  • Bis ffmpeg klappte es bei meinen Tests auch einwandfrei.

    Ich bin mir nicht ganz sicher ob wir hier nicht aneinander vorbei reden. Hier wird kein ffmpeg genutzt, sondern die Daten kommen vom inputstream-adaptive plugin.

    Und bei UDP ist es egal ob alles lokal läuft. Wenn der Empfänger die Daten nicht schnell genug abholt weil seine Puffer voll sind, dann gehen sie verloren.

  • Das Plugin habe ich um das Protokoll EXTT erweitert, das ähnlich wie EXT funktioniert, aber einen TCP (statt UDP) Socket öffnet.
    Dabei habe ich mich schamlos am control Plugin bedient (Dank an die Autoren).

    Getestet habe ich mit dem channels.conf Eintrag

    Code
    TCP Stream;IPTV:500:S=1|P=0|F=EXTT|U=iptvstreamtcp.sh|A=1:I:0:256=2:257=@4:0:0:2:1:1151:0

    Das Script iptvstreamtcp.sh ist neu und dient nur als Demonstration.

    Es ist schwach getestet funktioniert aber soweit ich das sehen kann. Tester sind natürlich erwünscht :)

  • Ich bin mir nicht ganz sicher ob wir hier nicht aneinander vorbei reden. Hier wird kein ffmpeg genutzt, sondern die Daten kommen vom inputstream-adaptive plugin.

    Ich denke es ist irgendwie nicht klar geworden, worauf ich hinaus will.
    Wir verwenden unterschiedliche Zuspieler, haben aber den gleichen Fehler.

    Bei mir gibt es aber keine Möglichkeit die Datenrate zu beeinflussen, da es sich um einen Live-Stream handelt.
    (ffmpeg packt den Datenstrom nur in .ts um, das ist aber eigentlich unerheblich und das scheint auch einwandfrei zu funktionieren.)

    Der Knackpunkt ist, dass sich jetzt das IPTV-Plugin an den Datenstrom anpassen muss, sonst wird Live-TV nie funktionieren. (zumindest wüsste ich nicht wie)

    Ich denke, die eigentliche Ursache liegt irgendwo beim Ringbuffer im IPTV-Plugin, überblicke das Konstrukt aber nicht.
    Wenn ich aber nicht völlig daneben liege, läuft der Ringbuffer leer, obwohl kontinuierlich Daten zugeführt werden!
    Der Füllstand des internen Ringbuffers sollte dem Plugin bekannt sein, es müsste also entsprechend regeln können, tut es aber wohl nicht.
    Bei den DVB-Karten klappt das doch auch irgendwie, die liefern die Daten ja auch in der Geschwindigkeit in der sie wollen.
    An dem Punkt bin ich dann aber raus gekommen ....

    Gruss
    SHF

    Mein (neuer) VDR:

    Software:
    Debian Wheezy mit Kernel 3.14
    VDR 2.0.7 & div. Plugins aus YaVDR-Paketen
    noad 0.8.6

    Hardware:
    MSI C847MS-E33, onboard 2x1,1GHz Sandybridge Celeron 847, 4GiB RAM
    32GB SSD (System), 4TB 3,5" WD-Red HDD (Video)
    TT FF DVB-S 1.5 FullTS-Mod PWM-Vreg-Mod, DVB-Sky 852 Dual DVB-S2
    Das ganze im alten HP Vectra VLi8-Gehäuse versorgt von:
    PicoPSU-160-XT und Meanwell EPP-150 im ATX-NT-Gehäuse

  • Bei mir gibt es aber keine Möglichkeit die Datenrate zu beeinflussen, da es sich um einen Live-Stream handelt.

    Bei mir ist es auch ein Livestream. Wenn bei dir ffmpeg die Daten liefert und die Puffer langsam leer laufen, dann ist entweder ffmpeg nicht schnell genug oder die Daten kommen im Download nicht schnell genug an.

  • Wenn bei dir ffmpeg die Daten liefert und die Puffer langsam leer laufen, dann ist entweder ffmpeg nicht schnell genug oder die Daten kommen im Download nicht schnell genug an.

    Das Kuriose ist aber, dass es zu funktionieren scheint, wenn ich den UDP-Stream mit dem Xine-Player öffne.

    Für mich sieht es daher noch immer so aus, als ob das IPTV-Plugin da zumindest mit Schuld hat.

    Gruss
    SHF

    Mein (neuer) VDR:

    Software:
    Debian Wheezy mit Kernel 3.14
    VDR 2.0.7 & div. Plugins aus YaVDR-Paketen
    noad 0.8.6

    Hardware:
    MSI C847MS-E33, onboard 2x1,1GHz Sandybridge Celeron 847, 4GiB RAM
    32GB SSD (System), 4TB 3,5" WD-Red HDD (Video)
    TT FF DVB-S 1.5 FullTS-Mod PWM-Vreg-Mod, DVB-Sky 852 Dual DVB-S2
    Das ganze im alten HP Vectra VLi8-Gehäuse versorgt von:
    PicoPSU-160-XT und Meanwell EPP-150 im ATX-NT-Gehäuse

  • Ich wüsste nicht, wo ich da ansetzen sollte.

    Schade, ich hatte die Hoffnung, dass irgendjemand, der das Plugin besser kennt wenigstens sowas wie eine vage Idee hat.

    Die Hauptschleife in streamer.cpp liest die Daten und füllt den internen Buffer (Default size 2 MB).

    Könnte man in den 10ms sleep den UDP-Socketbuffer voll schreiben?
    Der ist nicht groß (~200kiB) und ohne physikalisches Netzwerk gibt ja eigentlich keine Begrenzung in der Schreibgeschwindigkeit.

    Der Überlauf wäre mir dann zwar entgangen, aber das muss ja nicht permanent auftreten und man kann die Augen auch nicht überall haben.


    Immerhin ein Ansatz, denke ich.
    Wenn ich mal wieder etwas mehr Zeit habe, werde ich das noch mal ansehen.

    Gruss
    SHF

    Mein (neuer) VDR:

    Software:
    Debian Wheezy mit Kernel 3.14
    VDR 2.0.7 & div. Plugins aus YaVDR-Paketen
    noad 0.8.6

    Hardware:
    MSI C847MS-E33, onboard 2x1,1GHz Sandybridge Celeron 847, 4GiB RAM
    32GB SSD (System), 4TB 3,5" WD-Red HDD (Video)
    TT FF DVB-S 1.5 FullTS-Mod PWM-Vreg-Mod, DVB-Sky 852 Dual DVB-S2
    Das ganze im alten HP Vectra VLi8-Gehäuse versorgt von:
    PicoPSU-160-XT und Meanwell EPP-150 im ATX-NT-Gehäuse

  • Der Überlauf wäre mir dann zwar entgangen, aber das muss ja nicht permanent auftreten und man kann die Augen auch nicht überall haben.

    Bei einem Überlauf im Ringbuffer würde ich vom VDR eine Fehlermeldung (im syslog) erwarten.

    Könnte man in den 10ms sleep den UDP-Socketbuffer voll schreiben?

    Der UDP Buffer ist tatsächlich so klein.

    Code
    cat /proc/sys/net/core/wmem_default 
    212992

    Wenn die Pakete jetzt sehr schnell in Schüben geliefert werden, kann ich mir gut vorstellen, daß der überläuft. Ich sehe 2 schnelle Testmöglichkeiten:

    - Die Zeit von 10ms reduzieren. Siehe hier.
    - Den UDP Buffer vergrößern:
    sudo sysctl -w net.core.rmem_max=26214400
    sudo sysctl -w net.core.rmem_default=26214400

    Wer könnte denn eine der Varianten testen und die Erfahrungen mitteilen?

  • Das Erhöhen des UDP-Buffers hat bei mir in Verbindung mit dem IPTV-Plugin sehr viel geholfen.
    Auf die Idee hatte mich damals carel gebracht, der mir hier bei dem Empfang von Zattoo über das IPTV-Plugin sehr viel geholfen hat!
    Siehe hier : RE: Gibt es eine Alternative zu DVB-C welche mit VDR funktioniert?

    Allerdings ist mein Wert jetzt nicht ganz so groß, sondern "nur":
    net.core.rmem_max=2097152
    net.core.rmem_default=2097152
    net.core.wmem_max=2097152
    net.core.wmem_default=2097152

    Diese Werte habe ich einfach am Ender der /etc/systctl.conf eingefügt, damit diese bei jedem Start automatisch geladen werden.
    Damit klappt es bei mir schon sehr gut und ich kann einwandfrei, mit sehr, sehr seltenen Bildstörungen, die Streams von Zattoo empfangen.
    Vielleicht teste ich mal bei Gelegenheit die von Dir vorgeschlagenen größeren Werte.

    Auf jeden Fall kann ich sagen, dass es ohne die Vergößerung des UDP-Buffers vorher ständig Bildstörungen/Artefakte gab.
    Und nun im Prinzip gar nicht mehr, wenn dann sind es vermutlich eher Probleme mit dem Internet.

    meine aktuelle Hard- und Software

    Heimkino: . . . . . . . AVR Denon AVR-X4800H . . . MiniLED-UHD-TV SONY BRAVIA XR-75X95L. . . Universal-FB: Sofabaton U2
    VDR-Hardware: . . Grafik MSI GT1030, Quad-DVB-C/T2 TBS-6205, Quad-DVB-S2/S2X TBS-6904SE

    VDR-Software: . . . yaVDR-ansible-noble - Kernel 6.08.0 - VDR-2.7.x - nvidia-550
    VDR-Client 1+ Media-Player: . . . Odroid N2 . 4GB mit VDR*ELEC Kodi-21.x + VDR-2.7.x_@Zabrimus
    VDR-Client 2+ Media-Player: . . . Dune HD Homatics Box R4K Plus . 4GB mit Kodi-21.x + VDR-2.7.x_@Zabrimus

  • Auf jeden Fall kann ich sagen, dass es ohne die Vergößerung des UDP-Buffers vorher ständig Bildstörungen/Artefakte gab.

    Okay. Dann scheint es tatsächlich an den Buffern zu liegen und ist eher eine Systemkonfiguration. Die 10ms im Code kann ich auch reduzieren, aber ich will die Systemlast nicht hochtreiben.

    Vielleicht teste ich mal bei Gelegenheit die von Dir vorgeschlagenen größeren Werte.

    Die Werte waren einfach nur Beispiele. Von einem Extrem (zu niedrig) zu einem anderen Extrem (viel zu hoch, die Beispielwerte). Wenn es soweit keine Probleme gibt, würde ich es auch nicht ändern.

  • Bei einem Überlauf im Ringbuffer würde ich vom VDR eine Fehlermeldung (im syslog) erwarten.

    Ja, da war was im Log, darum bin ich überhaupt drauf gekommen.
    Die Meldung kam aber eher selten, wenn ich das recht erinnere.

    Irgendwie bin ich dann auch irgendwie an Füllstand vor Ringbuffer gekommen. (Ist jetzt ein halbes Jahr her, Details erinner nicht mehr.)
    Der Füllstand war für meinen Geschmack jedenfalls immer verdächtig niedrig. Was aber mangels Vergleich auch eine Fehleinschätzung sein kann.

    Wobei, ein leer gelaufener Ringbuffer ja auch Folge eines massiven (evtl. aber nur kurzen) Überlaufs im UDP-Socketbuffer sein, wenn man genau überlegt.

    Vielleicht teste ich mal bei Gelegenheit die von Dir vorgeschlagenen größeren Werte.

    Das wäre echt hilfreich!
    Wenn ich das recht erinnere, hattest Du damals die meisten Probleme.

    Bei mir geht es mit den Grundeinstellungen eigentlich.
    Zumindest meist ein paar Minuten lang, bis es dann irgendwann zu mehr oder weniger schweren Fehlern kommt.
    Das ist zum Testen nicht so wirklich ideal, da man nie weiß, ob die Einstellung was brachte, oder ob man einfach nur Glück hatte.

    Dann scheint es tatsächlich an den Buffern zu liegen und ist eher eine Systemkonfiguration.

    Die Voreinstellung ist AFAIK immer gleich niedrig :(.

    Die 10ms im Code kann ich auch reduzieren, aber ich will die Systemlast nicht hochtreiben.

    Das mögliche Minimum ist 3ms.
    Ich denke nicht, das man das groß merkt.

    Problematisch ist in dem Zusammenhang, das einem da auch der Scheduler einen Streich spielen kann und die Zeiten u.U. länger werden als gewünscht.

    Bei Xine scheint man da einige Klimmzüge gemacht zu haben, das macht man nicht ohne Grund.
    (Auch wenn das ganze Konstrukt bei mir momentan mehr Fragen aufwirft als zu beantworten.)

    C++
        /* System calls are not a thread cancellation point in Linux
         * pthreads.  However, the RT signal sent to cancel the thread
         * will cause recv() to return with EINTR, and we can manually
         * check cancellation.
         */

    https://sourceforge.net/p/xine/xine-lib/ci/default/tree/src/input/input_rtp.c#

    zu einem anderen Extrem (viel zu hoch, die Beispielwerte)

    Viel zu hoch würde ich bei 25MiB nicht sagen.
    Bei den Datenraten und wenn man ~1s puffern will wären 5-10MiB angemessen. (ffmpeg puffert auch 1 oder 2 Sekunden und die Daten sollten schon rein passen.)

    Bei net.core.?mem_max=26214400 hätte ich keine Bedenken. net.core.?mem_default würde ich aber ungern auf 25MiB hoch jagen, das beeinflusst ja alle Puffer.

    C++
      #define BUFFER_SIZE (1024*1024)
      
      /* Try to increase receive buffer to 1MB to avoid dropping packets */
      optval = BUFFER_SIZE;
      if ((setsockopt(s, SOL_SOCKET, SO_RCVBUF,
    		  &optval, sizeof(optval))) < 0) {
        LOG_MSG(xine, _("setsockopt(SO_RCVBUF): %s.\n"), strerror(errno));
        return -1;
      }

    Xine scheint zu versuchen den Puffer zu erhöhen (was bei mir natürlich dank niedrigem net.core.rmem_max normalerweise nicht funktioniert hat).

    Evtl. sollte man das so ähnlich auch rein nehmen, dann reicht net.core.rmem_max zu setzen?
    Für TCP schadet ein größerer Puffer sicher auch nicht.

    Gruss
    SHF

    Mein (neuer) VDR:

    Software:
    Debian Wheezy mit Kernel 3.14
    VDR 2.0.7 & div. Plugins aus YaVDR-Paketen
    noad 0.8.6

    Hardware:
    MSI C847MS-E33, onboard 2x1,1GHz Sandybridge Celeron 847, 4GiB RAM
    32GB SSD (System), 4TB 3,5" WD-Red HDD (Video)
    TT FF DVB-S 1.5 FullTS-Mod PWM-Vreg-Mod, DVB-Sky 852 Dual DVB-S2
    Das ganze im alten HP Vectra VLi8-Gehäuse versorgt von:
    PicoPSU-160-XT und Meanwell EPP-150 im ATX-NT-Gehäuse

  • Evtl. sollte man das so ähnlich auch rein nehmen, dann reicht net.core.rmem_max zu setzen?
    Für TCP schadet ein größerer Puffer sicher auch nicht.

    Ich habe das in das Plugin aufgenommen. Falls die Vergrößerung nicht funktioniert (net.core.rmem_max zu klein) dann passiert halt nix.

Participate now!

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