Beiträge von Zabrimus

    Im Endeffekt ist das ganz einfach, man muss nur "state = osContinue" in ProcessKey() regelmäßig zurückgeben. Solange das passiert, bleibt das OSD auch offen.

    Genau darauf bin ich auch schon gekommen und das ist die Lösung. Ich habe den Thread und alle Spuren aus dem Plugin entfernt. Heute kam ich auch dazu, die Pause zu testen und auch die bleibt jetzt offen und wird nicht mehr geschlossen.

    Es kann alles so einfach sein, wenn man darauf kommt ;)


    Den Entwicklungsbranch des Browsers habe ich jetzt auch gemerged. Allerdings sollte man Videos der Privaten (S1, P7) nur probieren, wenn man ausgesprochen mutig ist. Im Besten Fall sieht man nur nur eine Endlosschleife von Werbung. Der schlimmste Fall sollte nach einer Änderung im Plugin nicht mehr auftreten - hoffentlich.

    Durch die Nutzung von mutation-summary (Javascript) bekomme ich jetzt nicht mehr alle Kleinigkeiten der DOM-Änderung (Videosize und dergleichen) mit, sondern nur noch eine Zusammenfassung. Das ist viel angenehmer zu handlen. Ich muss jetzt nur noch das video-Tag auch erkennen, das RedButton geschickt einschmuggelt, um dann die URL zu ändern.


    Habe ich eigentlich schon erwähnt, daß ich mit Javascript nicht viel anfangen kann? Ich werde damit einfach nicht warm, egal wie oft ich es versuche.

    Ich frage mich schon die ganze Zeit, wieso Du das OSD überhaupt offen halten musst.

    Ich hatte kurz Zweifel. Aber wenn ich im Plugin das cRemote::TriggerLastActivity(); entferne, dann schließt sich das WebOsd nach 2 Minuten selbstständig. Mit dem Trigger bleibt das OSD offen und man kann weiter auf der Seite navigieren.

    Das automatische Schließen hat den Nachteil, daß man erst wieder über das Menu das OSD öffnen muss und evt. wieder zum Ziel navigieren muss.


    Also muss in TVGuide noch irgendwas anders sein.


    Edit:

    Nach einem weiteren Check, habe ich eine Möglichkeit gefunden, auf den Trigger-Thread zu verzichten. Das schaffe ich heute nicht mehr, aber dann fliegt eine ungeliebte Funktionalität aus dem Plugin :) Dann muss ich nur noch schauen, ob das auch Auswirkungen auf die Pause hat.

    Hmm... Das Dummy-OSD wird automatisch geschlossen und damit beginnt die Kaskade

    Entweder das das DummyOSD noch zu sehr dummy, oder der Mechanismus zum offenhalten funktioniert noch nicht richtig.

    Ich starte das Plugin mit '-o' und der Browser ist unschuldig. Der Trigger zum Schließen kommt aus dem VDR oder dem Plugin.

    Das OSD versuche ich offen zu halten (triggerActivityThread in WebOsdPage). Der Player bekommt während der Pause auch keine Events mehr, muss dieser auch irgendwie offen gehalten werden?

    Ich fürchte da müssen ein paar Debug-Meldungen ins Plugin und der VDR Code mal wieder gelesen werden.

    Nächstes Problem: Nach einiger Zeit im Film wird er abgebrochen. Da passiert immer nach ca. 2 min und folgendes ist im Log

    Passiert das tatsächlich bei jedem Film? Immer? Startest du das Plugin mit '-o' oder ohne?

    Aug 14 10:52:24 Odroid vdr[4862]: [4862] [vdrweb] Destruct WebOSDPage, osdMode 1

    osdMode 1 ist der Player. Damit wird der Player auf nullptr gesetzt und im MainMenuHook dann final geschlossen.

    Oder meinst du daß während der Pause der Player auf einmal geschlossen wird?


    Edit:

    Ich konnte das nachstellen. Die Pause wird tatsächlich durch den Browser beendet. Bzw. irgendwas bringt den Browser dazu, den Context zu schliessen und damit auch ein StopVideo an VDR zu senden.

    Ich muss versuchen, ob ich an die Javascript-Console Ausgaben ran komme um zu sehen, ob da etwas geloggt wird. Der Chrome-Debugger verliert die Ausgaben genau in dem Moment, in dem es spannend wird.

    Ich muss mir nochmal anschauen wie der VDR einen neuen stream ankündigt. Ich denke da kommt erst ein SetPlayMode 0 und dann ein SetPlayMode 1.

    Das führt dazu das ich intern die Buffer lösche und bei SetPlayMode 1 erst die Buffer wieder auffülle bevor ich den Stream abspiele. Sendest du auch die SetPlayModes ? Ich schau es mir auch nochmal an.

    PlayModes? Vielleicht passiert das intern, aber aktiv mache ich das nicht.


    Es gibt 2 Möglichkeiten ein Video abzuspielen:

    1. Frisches Video: Aus dem Live-TV wird ein Video ausgewählt

    Das passiert in

    vdrServer.Get("/StartVideo", [](const httplib::Request &req, httplib::Response &res)

    Ein Player wird konstruiert und an das Device attached.

    2. Ein Video soll abgespielt werden, während der Player noch aktiv ist. Also wenn z.B. ein Video abgespielt wird und man direkt das nächste aussucht oder automatisch abgespielt werden soll.

    Das passiert in

    vdrServer.Get("/ResetVideo", [](const httplib::Request &req, httplib::Response &res)

    Hier rufe ich videoPlayer->ResetVideo(); auf, was dann intern in

    cPlayer::DeviceClear(); mündet.

    Ich habe sowohl den Browser, als auch den Transcoder erweitert, so daß beide direkt gestoppt werden, wenn das Listen fehlschlägt. Zusätzlich sollte eine Fehlermeldung ausgegeben werden, mit dem hoffentlich die Ursache ermittelt werden kann.


    Wo genau das Problem liegt kann ich leider nicht finden. Dafür ist mir der Datenfluss zu unklar :)

    Das ist eigentlich ganz simpel:


    Der Reader-Thread im Transcoder liest alles aus dem FIFO aus:

    Code
    if ((bytes = read(fifo, buffer, sizeof(buffer))) > 0) {
        if (!client->ProcessTSPacket(std::string(buffer, bytes))) {

    Der Transcoder ruft folgendes auf

    Code
    bool BrowserClient::ProcessTSPacket(std::string packet)
    -> client->Post("/ProcessTSPacket", packet, "text/plain")

    Im Browser werden die Pakete empfangen

    Code
    // called by transcoder
    svr.Post("/ProcessTSPacket", [&vdrRemoteClient, &transcoderRemoteClient](const httplib::Request &req, httplib::Response &res) {

    und dann direkt an VDR weitergeleitet

    Code
    vdrRemoteClient.ProcessTSPacket(std::string(body.c_str(), body.length())

    Das Plugin empfängt das Paket

    Code
    vdrServer.Post("/ProcessTSPacket", [](const httplib::Request &req, httplib::Response &res)

    und schiebt es dann Richtung Ausgabedevice

    Code
    videoPlayer->PlayPacket((uint8_t *) body.c_str(), (int) body.length());

    Also wird alles, was der Transcoder von FFmpeg aus dem FIFO bekommt 1:1 im Plugin bzw. Ausgabedevice landen. Dazwischen findet keine Umwandlung oder sonstige Manipulation statt.

    Kann das es dann ein Problem mit den Sockets sein, wenn cefbrowser und remotrans nicht in einem Terminal laufen?

    Alle 3 Komponenten (browser, transcoder und das Plugin) nutzen exakt dieselbe Library. Der einzige Unterschied ist der zu verwendende Port. Und VDR bzw. das Plugin haben keine Probleme mit dem Start? Ich muss mal schauen, ob ich an mehr Informationen komme, warum der Listen schief.


    Zabrimus Ich habe nun mal das kurze Stottern des Bildes analysiert und es sieht so aus das mein Videopuffer leerläuft. D.h. die Buffer werden nicht genug gefüllt.

    Puhhh... Ich habe gerade das genaue gegenteilige Problem mit dem Puffer. Im syslog sieht es so aus, als ob die Puffer vollaufen und dadurch nur ein Standbild angezeigt wird. Ich arbeite gerade an den Privatsendern (s1p7) und da sind noch zuviele offene Punkte, als das ich meinem Problem weitere Beachtung schenken kann. Unklar ist noch, ob es an den Sendern bzw. dem Browser liegt.

    Und es bleibt das Problem mit den 48 KHz Audio-Filmen, die auch der Parameter -t codecs.ini nicht löst.

    Das vestehe ich nicht. Bekommst du 48 KHZ und es macht Probleme, oder bekommst du etwas anderes als 48 KHZ? Für den Audiotranscode gibt es verschiedene Varianten.

    Wie genau sieht dein audio/codec_copy und audio/transcode in der codecs.ini aus und welches Zielformat funktioniert ohne Probleme?

    Und hier die "finale" Version

    Ich hätte bis gerade Stein und Bein geschworen, daß der 188-Byte Puffer-Größen-Check entweder im Browser oder dem Plugin vorhanden ist. Unklar ist nur, wann und wo ich das verloren habe.

    Ich habe deine Version 1:1 übernommen. Danke!

    Hierbei habe ich wieder ein schwarzes Bild um das skalierte Fenster, wenn das VDR-OSD weg geht.

    Da müßte also auch noch irgenwo ein "browserClient->ReloadOSD();" hin.

    Das Problem besteht darin, festzustellen, wann genau das VDR OSD mit der Lautstärkeregelung ausgeblendet wird um dann das Reload zu triggern. Dazu fällt mir keine richtig gute Lösung ein.


    Die Version mit "-o" läuft so, wie ich es erwarten würde. Was noch top wäre, wäre eine web-eigene Lautstärkeanzeige. Geht aber auch so.

    Genau das habe ich doch im Browser und Plugin gestern vorbereitet. Ich muss noch testen, ob es auch in allen Situationen funktioniert.


    Ich stelle später einen Patch ein, der eine ganz einfache Lautstärkeanzeige darstellt bzw. darstellen soll.

    kamel5 Ich starte übrigens mit "-o"

    Ein Problem ist noch das Löschen. Das passiert auch erst, wenn ein OSDUpdate kommt.

    Genau die Frage habe ich mir gerade gestellt. Deine Patches beziehen sich auf "-o"? Ich fürchte, wir sind uns gerade in die Quere gekommen :(

    Man kann jetzt z.B. auch folgendes machen:

    Das ist aber nicht Sinn der Sache.

    Ich finde das Verhalten, das kamel5 beschreibt eigentlich ganz cool, kann aber auch jojo61 verstehen.

    Und um beiden Ansprüchen gerecht zu werden, gibt es (aktuell nur im Branch osd_rework) den Plugin-Parameter '-o' / '--dummyosd'.

    Ohne den Parameter sieht man das Verhalten von kamel5. Mit Parameter das Original-Verhalten, wie es auch noch im Master-Branch vorhanden. Bei Gelegenheit werden ich dev-Branch mergen, da jetzt das Verhalten mit der Lautstärke konfiguriert werden kann:


    -o: Kein Lautstärke-OSD, Altes Verhalten

    ohne -o: Lautstärke-OSD, Neues Verhalten

    Du öffnest das OSD als Layer 5 aber die Pixmaps erstellst du als Layer 1

    Layer 5 macht keinen Unterschied, wie ich sehe. Aber das softhddevice (von ua0lnj, lnj) im opengl-modus macht genau das Richtige und es sieht so aus, wie es soll:



    Nur was da anders gemacht wird, weiß ich nicht. Ich habe noch nicht einmal die Diskussion mit Pixmap Layer 0 verstanden. Also wenn jemand eine Lösung findet, wäre das toll.

    Aber das Web hat doch ein OSD offen (z.b. bei der Taggesschau) und doch macht der vdr das Lautstärkemenü auf das sich dann ja beisst. Warum ??

    Die Bedingung ist im VDR hinterlegt. Es wird nicht aufgemacht, wenn es ein Menu ist und der Layer des OSD 0. Oder so ähnlich. Deshalb kam ich auf die Idee, den Layer auf 0 zu setzen, aber das hat andere Konsequenzen.

    Wer es ausprobieren will, kann das in der Klasse (webosdpage.cpp) ändern:

    Code
    void WebOSDPage::Display() {
        dsyslog("[vdrweb] WebOSDPage Display\n");
        if (osd) {
            delete osd;
        }
    
        osd = cOsdProvider::NewOsd(0, 0, 5); <== Aktuell ist Layer 5

    Ich habe das gerade mal mit einem echten Video probiert. Solange das OSD sichtbar ist, ist die Lautstärke-Regelung ungünstig. Aber mit der Zeit wird das OSD des Videos ausgeblendet und dann funktioniert die Lautstärke-Regelung perfekt und wie gewünscht.

    Bei der Tagesschau geht es richtig schief durch die Laufschrift und weil das OSD nicht wirklich ausgeblendet wird.

    Sobald man das Tagesschau-Video auf Vollbild schaltet (zum Videofenster navigieren und ok drücken) und das WebOSD weg ist, dann sieht es auch wieder perfekt aus.


    Das Problem entsteht also, wenn im WebOSD etwas dargestellt wird und dann die Lautstärke-Regelung benutzt wird. Die Kombination beider OSD (Web + Lautstärke) ist exakt das Problem.


    Edit:

    Es entsteht eine Konkurrenzsituation, in der beide OSD jeweils etwas anzeigen wollen und sich dabei aber gegenseitig in die Quere kommen.

    M.E. müsste zuerst der Konstruktor von page das OSD erzeugen und der Destruktor es wieder zerstören. D.h. zu einer webosdpage gehört ein OSD.

    Genau das passiert ja. In einer linearen Welt wäre das auch einfach. Das Problem ist das es Momente gibt, in dem sowohl das Osd des Players, als auch das Osd des Menus existieren. Wenn ich z.B. von einem Player zu dem normalen Menu OSD wechsle, passiert genau das:

    Player wird detached

    Menu-Osd wird gestartet

    Destructor vom Player-OSD wird aufgerufen.

    Im genau hier im Destructor muss ich aufpassen, welche der beiden WebOSD gerade gelöscht wird und mir das gerade aktuell weiter existierende merken und umgekehrt eben auch, damit Get() das wirklich aktive zurückgibt.


    Das Problem ist herauszufinden, wann ich das WebOSD tatsächlich brauche. Dazu müsste ich im Browser herausfinden, wann das OSD vollständig transparent ist und wann nicht. Und das bei jeder Aktualisierung. Ich fürchte, das wird dann wirklich zu einer Bremse. Deshalb bleibt das OSD (ob Player oder Menu) immer offen und wird erst geschlossen, wenn das Plugin wirklich zu ist.

    Die Lautstärketasten lassen sich wohl nicht abfangen, die werden in vdr.c in der Hauptschleife abgefragt.

    Ich habe versucht, ob es nicht doch zum Plugin gelangt, ohne Erfolg. Das finde ich auch in der Doku zu VDR:

    Zitat

    cMyControl will receive the user's key presses through the ProcessKey() function. It will get all button presses, except for the volume control buttons (kVolUp, kVolDn, kMute), the power button (kPower) and the menu button (kMenu).


    Aber das Wichtigste wäre wohl erstmal, dass sich der VDR nicht mit seinem OSD ins Plugin schleicht...

    Das ist das, was ich nicht verstehe. Nutze ich Layer 0 für das WebOSD, wird finde ich im syslog das hier

    Code
    vdr: [3935768] ERROR: attempt to open OSD while it is already open - using dummy OSD!

    Und bei der Meldung wird ein Dummy OSD in cOsd *cOsdProvider::NewOsd mit Layer 999 erzeugt. Das OSD vom Player ist nicht sichtbar, aber das Lautstärke-OSD ist da und funktioniert.

    Wieviele OSDs gibt es denn da gleichzeitig?

    "Womit" flackert es denn?

    Wenn ich Zeit hab schau ichs mir auch nal an, aber das muss lösbar sein...


    Der VideoPlayer besteht aus dem Player einem cWebOSDPage als Control, der für das Player-OSD zuständig ist.


    Alte Version:

    Da wurde das Menu-OSD cWebOSDPage nicht richtig geschlossen und existierte weiterhin, auch wenn ein Video abgespielt wurde. Ein Schliessen des Menu-OSD führte zu segfaults, die auch hier im Thread erwähnt wurden.

    Im Prinzip gab es 2 Instanzen von cWebOSDPage (Menu + PlayerControl).


    Neue Version:

    Das Menu-OSD wird tatsächlich und in echt geschlossen, wenn ein VideoPlayer mit einem cWebOSDPage als Control geöffnet wird. Damit gibt es nur eine eine Instanz von cWebOSDPage.


    Jetzt kommt die Lautstärkeregelung ins Spiel. In der alten Version wurde nichts angezeigt, weil schon ein Menu-OSD existierte. In der neuen Version hingegegen gibt es kein Menu-OSD und die Regelung vom VDR wird angezeigt.

    Und damit gibt es eine Kollision, die gerade bei der Tagesschau besonders sichtbar ist, weil der Bereich, der vom Browser permanent aktualisiert wird (Laufschrift) mit der Lautstärke-Anzeige vom VDR uberlappen.

    Die Lautstärke-Anzeige scheint ein Fullscreen-OSD zu sein und damit wechseln sich Lautstärke und Update des Browsers permanent ab. Die Anzeige wechselt von "schwarzer Hintergrund + Lautstärke" mit "Browser-OSD". Und das ergibt das Flackern.


    Deshalb hatte ich es mit den Layern im Plugin probiert, weil ich dachte, Layer 0 ganz unten und darauf dann die Lautstärke, aber das Result war ein nahezu schwarzer Bildschirm mit verkleinertem Video, aber funktionierender Lautstärke-Anzeige.

    Ab Layer 1 entsteht wieder das Flackern.


    Aktuell habe ich shady_kiss von skindesigner als Skin.


    Ich weiß gar nicht, wie ich die Lautstärke "abfangen" und als Image in das Browser-OSD integrieren kann. In einem meiner Prototypen (https://github.com/Zabrimus/vdr-plugin-webout) habe ich ein Device geschrieben um an das OSD als Bild zu kommen, aber das ist hier keine Lösung. Ein temp. Skin klingt auch nicht wirklich überzeugend.

    Und ich wollte noch fragen, ob man nicht die Lautstärkeregelung von VDR oder was anderes einblenden kann. Deaktivieren muss ja irgendwie gehen, vorher kams ja auch nicht. Flackern sollte natürlich nichts. Ich werde den Branch später mal testen.

    Deaktivieren war eigentlich ein Fehler, den man natürlich reproduzieren kann. Die Ursache war einfach, daß ich das OSD aus dem Menu nicht wirklich geschlossen hatte und damit die Anzeige der Lautstärkeregelung unterbunden wurde. Versuchsweise habe ich den aktuellen OSD-Layer auf 0 gesetzt, aber dann ist in der Tagesschau nur das Video zu sehen, dafür flackert die Lautstärke-Anzeige nicht mehr. Auch nicht gut. OSD-Layer ab 1 flackert dann wieder.

    Ich habe nun mal in das Outputfile geschaut und da sind die 000001 Prefixe drin. Ist also auch ohne recoding ein h264 Stream und nicht mehr avc1.

    Du kannst den Parameter lassen wo er ist. Da macht der ffmpeg keinen Fehler und das Problem liegt wohl woanders mit der TT6400.

    Wunderbar. Danke für die Prüfung. Ich habe weder die Karte, noch das passende Plugin, noch irgendwas, was zur Hilfe beitragen kann.


    Für das Plugin gibt es den Branch rework_osd, darin sieht das Handling Osd/Player-Control viel logischer aus. Das OSD wird geschlossen, wenn nicht benötigt und es gibt eine Trenung OSD und Player/Control, obwohl es beides dieselbe Klasse ist, wird nun sauber differenziert.

    Es gibt nur 2 extreme Nachteile, die mich nerven:

    1. Z.B. die Lautstärke Regelung vom VDR wird eingeblendet und dabei entsteht ein sehr unangenehmes Flackern, oder sogar ein schwarzes Bild mit dem Video oben rechts bei der Tagesschau. Ich hätte gedacht, daß kein VDR OSD mehr eingeblendet wird, wenn ein Player/Control aktiv ist, aber da habe ich mich wohl getäuscht. Auf dem Zielrechner ist mir das egal, weil die Regelung über den Fernseher stattfindet, aber auf dem Rechner ist das furchtbar.

    2. Jetzt schmiert mir sws_scale auch ab. Gar nicht reproduzierbar. Ich muss da schon schnell zwischen verschiedenen Videos wechseln und irgendwann kracht es dann. Das geht mal gar nicht.


    Jetzt versuche ich, sws_scale zu ersetzen durch GraphicsMagick. Nur funktioniert das so gar nicht und ich habe keinen Plan mehr.


    Im Moment sieht der Code so aus:

    Code
    Magick::Blob blob(image, width * height * 4);
    Magick::Image mimage;
    mimage.size(Magick::Geometry(width, height));
    // mimage.magick("BGRA");
    mimage.magick("RGBA");
    mimage.read(blob);
    mimage.sample(Magick::Geometry(osd_width, osd_height));

    Nur passiert nach mimage.read(blob); nichts mehr. Ich komme nicht einmal zum sample. Keine Fehlermeldung, kein nix. Ich weiß nicht einmal, wo sich die Ausführung befindet oder ob das read einfach nur sehr sehr lange braucht.


    Edit: resample gelöst.

    Code
    Magick::Image mimage;
    mimage.read(width, height, "RGBA", static_cast<const MagickLib::StorageType>(0), image);
    mimage.sample(Magick::Geometry(osd_width, osd_height));
    mimage.write ( 0, 0, osd_width, osd_height, "RGBA", static_cast<const MagickLib::StorageType>(0), scaled);

    Damit ist zumindest in dem Branch die Abhängigkeit von sws_scale weg und dafür gibt es nun GraphicsMagick++.

    Ja er könnte an der falschen Stelle sein oder sich mit dem copy beißen.

    Das sample auf der FFmpeg Homepage macht das fast genauso:

    ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts.. Man könnte natürlich versuchen, den Filter im Transcoder direkt vor das "-f mpegts" zu schieben und schauen, ob das einen Unterschied macht.


    Code
    if (s.codec == "h264" && s.codec_tag == "avc1") {
     callStr.emplace_back("-bsf:v");
     callStr.emplace_back("h264_mp4toannexb");
    }
    callStr.emplace_back("-f");
    callStr.emplace_back("mpegts");
    callStr.emplace_back(fifoFilename);

    Leider ist avc1 nicht gleich h264. Und genau da ist das Problem mit der erkennung des Streams.

    Genau deshalb hatte ich Hoffnung, daß der FFmpeg Filter die Umwandlung zu einem "H.264 bitstream with start codes" gleich mit erledigt.

    Code
    2.12 h264_mp4toannexb
    
    Convert an H.264 bitstream from length prefixed mode to start code prefixed mode (as defined in the Annex B of the ITU-T H.264 specification).
    
    This is required by some streaming formats, typically the MPEG-2 transport stream format (muxer mpegts)

    Entweder funktioniert das nicht richtig, oder ich verwende den Filter falsch oder an der falschen Stelle. Dazu bin ich aber bei weitem nicht tief genug drin. Den Output-Muxer gebe ich mit "-f mpegts" auch schon an.