TrickSpeed - Verständnisfrage

  • jrie I would suggest optimizing the code.

    if (audio_clock != (int64_t) AV_NOPTS_VALUE
    && video_clock != (int64_t) AV_NOPTS_VALUE) {
    int diff;
    diff = video_clock - audio_clock - VideoAudioDelay;

    2 times the same code.

    Or make PR, I'll look further myself.

    vdr-2.6.4+(SoftHDDevice GT1030)+ss2 express HD+Behold TV H7+IPTV+PVR150MCE
    https://github.com/ua0lnj/

    Edited once, last by lnj (January 1, 2025 at 4:39 AM).

  • 2 times the same code.

    Yes, I saw it, too. But had not enough time.

    Or make PR

    Done.

  • 2 times the same code.

    In trickspeed and in stillpicture we are in a recording and all data are already available.
    Does that imply it is safe to assume audio clock and video clock have always valid value?
    If so, we could easily simplify the code by putting trickspeed and stillpicture code into that part of xxxSyncDecoder().

  • When you start playing, synchronization occurs immediately, slow playback is used after that. But I have never done video editing, maybe other cases are possible. Is trick speed possible with time-shift recording, or is it the same video playback?

  • it is safe to assume audio clock and video clock have always valid value?

    Not in case of audio only or video only.


    The only possibility I see for deduplication is:

    int calculate_video_audio_diff(void) {
       if (audio_clock != (int64_t) AV_NOPTS_VALUE && video_clock != (int64_t) AV_NOPTS_VALUE) {
           return video_clock - audio_clock - VideoAudioDelay;
       } else {
           return AV_NOPTS_VALUE;
       }
    }

    but I am not sure, if that makes sense.

  • Bei RPI-Trickspeed bin ich etwas weiter:

    Der decoder für RPI puffert Pakete, bevor er ein dekodiertes Frame ausgibt - bei H264 sind es z.B. mind. 10.
    Das ist bei play forward kein Problem. Bei trickspeed aber schon, da man ja eigentlich gleich das erste gesendete haben will. Bei backward trickspeed sortiert der decoder vor der Ausgabe nach pts und spuckt das mit dem kleinsten pts aus, d.h. die Reihenfolge beim Rückwärtslauf stimmt nicht. Der rockchip decoder z.B. spuckt gleich das Frame aus, das zum packet passt und da fällt es nicht auf.

    Die richtige Herangehensweise bei ffmpeg wäre, die Ausgabe des Frames zu erzwingen, in dem man direkt nach dem Senden des letzten erforderlichen packets mit einem Null-Packet den End-of-stream signalisiert und das Frame dann abfragt. Danach muss der decoder geflusht werden und es kann weitergehen. Bei rockchip funktioniert der flush, bei rpi (noch) nicht. Da muss aktuell noch der decoder geschlossen und wieder geöffnet werden, was recht teuer ist aber bei trickspeed wahrscheinlich nicht groß auffällt. Man wird das also hinkriegen.

    Das ganze setzt aber voraus, dass softhddevice mit den Daten, die von VDR kommen, ein komplettes AVPacket erzeugen kann, das ohne Referenzen auskommt, also ein I-Frame ist.
    In den ersten Posts steht schon, dass wir es mit I-Frames zu tun haben und die Stelle im Code müsste https://git.tvdr.de/?p=vdr.git;a=b…01;hb=HEAD#l522

    Sicherheitshalber, Frage nochmal an kls , bei Trickspeed ist sichergestellt, dass VDR immer "PTS-weise" Daten für ein komplettes I-Frame schickt?

    Nur dann könnte man nämlich ohne weitere Prüfung in softhddevice dieses Paket an den decoder schicken und mit einem End-of-stream die Ausgabe des Frames forcieren, weil der Dekoder es eigentlich ohne ein weiteres Frame verarbeiten können müsste.

    Meine VDRs

    (SatIP Server) --- Kathrein Exip 418 ---

    (Server) --- HW: RPI5 --- SW: RPiOs, VDR 2.7.2 mit streamdev, satip/vtuner-ng, vdrmanager, live, epgsearch, markad ---

    (Client 1+2) --- HW: Radxa Rock 4 Plus - RK3399 --- SW: VDR*ELEC mit softhddevice-drm-gles ---

    (WIP) --- Tanix TX6, RPi5, RPi4, Odroid N2+, WetekPlay2 --- SW: VDR*ELEC mit softhddevice-drm-gles --

  • Bei mir rennt der Fortschrittsbalken und die Zeit beim Anlaufen der Rückwärtstricksspeed am Anfang zu schnell zurück, bis sie sich nach ca. 1-2 Sekunden einpendelt und auf die richtige Zeit zurückspringt.

    Ist das bei euch auch so? Von softhddevice wird für SetCurrent() und SetProgress() m.E. nur GetSTC() benötigt, was es eigentlich richtig machen sollte.

    Mich interessiert nur, ob ich der einzige bin, da ich weiß, wo ich suchen muss. softhddevice, skin oder vdr...

    Meine VDRs

    (SatIP Server) --- Kathrein Exip 418 ---

    (Server) --- HW: RPI5 --- SW: RPiOs, VDR 2.7.2 mit streamdev, satip/vtuner-ng, vdrmanager, live, epgsearch, markad ---

    (Client 1+2) --- HW: Radxa Rock 4 Plus - RK3399 --- SW: VDR*ELEC mit softhddevice-drm-gles ---

    (WIP) --- Tanix TX6, RPi5, RPi4, Odroid N2+, WetekPlay2 --- SW: VDR*ELEC mit softhddevice-drm-gles --

  • kls Hier mal ein Log, das mein Problem mit dem falschen SetProgress vom vorherigen Post zeigt:

    https://paste.debian.net/plain/1347052

    Das Log hat folgenden Ablauf:

    - Abspielen der Aufnahme (DisplayReplay ist angezeigt)
    - Freeze
    - TrickSpeed slow back
    - Freeze

    Es werden sowohl SetProgress/SetCurrent vom Skin als auch DeviceGetSTC (=VideoGetClock) vom softhddevice geloggt. GetFrameNumber ist ein Log in https://git.tvdr.de/?p=vdr.git;a=b…01;hb=HEAD#l967

    Beim Rückwärtslauf nimmt Current zuerst sehr schnell ab, obwohl vom softhddevice mit GetSTC immer derselbe PTS kommt. Erst nach einer Zeit fängt sich das Ganze. Ich schließe daraus, dass in FindFrameNumber() (oder FindIndex?) irgendwas nicht passt? Hast du eine Idee?

    Meine VDRs

    (SatIP Server) --- Kathrein Exip 418 ---

    (Server) --- HW: RPI5 --- SW: RPiOs, VDR 2.7.2 mit streamdev, satip/vtuner-ng, vdrmanager, live, epgsearch, markad ---

    (Client 1+2) --- HW: Radxa Rock 4 Plus - RK3399 --- SW: VDR*ELEC mit softhddevice-drm-gles ---

    (WIP) --- Tanix TX6, RPi5, RPi4, Odroid N2+, WetekPlay2 --- SW: VDR*ELEC mit softhddevice-drm-gles --

  • kls Irgendsowas in der Art scheint da nötig zu sein:

    FindFrameNumber setzt die FrameNumber auf die letzte gefundene, wenn i = w-1, aber das scheint für trickspeed nicht zu stimmen. Nach meinem Verständnis müsste man da ins FindIndex fallback. Das wird aber nicht erreicht, weil nur gegen Valid geprüft wird, UnplayedIFrames aber (noch) nicht 0 ist. Habe ich das richtig verstanden?

    Meine VDRs

    (SatIP Server) --- Kathrein Exip 418 ---

    (Server) --- HW: RPI5 --- SW: RPiOs, VDR 2.7.2 mit streamdev, satip/vtuner-ng, vdrmanager, live, epgsearch, markad ---

    (Client 1+2) --- HW: Radxa Rock 4 Plus - RK3399 --- SW: VDR*ELEC mit softhddevice-drm-gles ---

    (WIP) --- Tanix TX6, RPi5, RPi4, Odroid N2+, WetekPlay2 --- SW: VDR*ELEC mit softhddevice-drm-gles --

  • Ich habe das gestern abend mal angetestet und es scheint soweit zu funktionieren. Ob das die beste Umsetzung ist, weiß ich nicht, da habe ich FindFrameNumber und FindIndex noch nicht ausreichend verstanden.

    Meine VDRs

    (SatIP Server) --- Kathrein Exip 418 ---

    (Server) --- HW: RPI5 --- SW: RPiOs, VDR 2.7.2 mit streamdev, satip/vtuner-ng, vdrmanager, live, epgsearch, markad ---

    (Client 1+2) --- HW: Radxa Rock 4 Plus - RK3399 --- SW: VDR*ELEC mit softhddevice-drm-gles ---

    (WIP) --- Tanix TX6, RPi5, RPi4, Odroid N2+, WetekPlay2 --- SW: VDR*ELEC mit softhddevice-drm-gles --

  • rell cPtsIndex::FindFrameNumber() funktioniert eigentlich nur für den "vorwärts" Betrieb. Für "rückwärts" ist das gar nicht ausgelegt. Bitte probier mal beiliegenden Patch, der im "rückwärts" Fall gleich cPtsIndex::FindIndex() aufruft. Damit tritt der Fehler zumindest bei mir nicht mehr auf.

  • Patch aus #113 tut, was er soll. Und beim #114er kann ich auf die Schnelle den Unterschied nicht erkennen. Er macht jedenfalls nichts böses :) Danke!

    Meine VDRs

    (SatIP Server) --- Kathrein Exip 418 ---

    (Server) --- HW: RPI5 --- SW: RPiOs, VDR 2.7.2 mit streamdev, satip/vtuner-ng, vdrmanager, live, epgsearch, markad ---

    (Client 1+2) --- HW: Radxa Rock 4 Plus - RK3399 --- SW: VDR*ELEC mit softhddevice-drm-gles ---

    (WIP) --- Tanix TX6, RPi5, RPi4, Odroid N2+, WetekPlay2 --- SW: VDR*ELEC mit softhddevice-drm-gles --

  • Bei mir hat der Patch aus #114 aber eine unschöne Nebenwirkung. Wenn man von "pause" nach "slow forward" wechselt, läuft die Wiedergabe nicht weiter sondern es gibt einen Sprung, vermutlich zum nächsten I-Frame. Das passiert bei mir sowohl auf dem Raspberry mit rpihddevice als auch auf dem PC mit dem dvbsddevice.

    Gruß Zimuland

  • Bei softhdodroid führt die Verlegung des Empty() dazu, dass nach dem Wechsel von Pause zu Slow Forward das Bild erstmal ein paar Sekunden stehen bleibt, ehe die Zeitlupe anläuft. Hat wohl was mit Buffering zu tun.

    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

  • Da muss ich das tatsächlich auch nochmal gescheit testen.

    Wenn ich mich richtig erinnere, schickt der VDR beim normalen Play den stream. Der wird bei Pause dann nicht gelöscht und befindet sich als "schon verarbeitet" im Puffer des Ausgabeplugins. Wenn dann jetzt SlowForward kommt, wird mit Empty/DeviceClear alles gelöscht, was schon gepuffert ist, aber VDR schickt die Daten nicht nochmal ab dem Pause-Zeitpunkt, sondern schickt nur die Daten weiter, die noch nicht geschickt wurden. Dann fehlt ein Stück. Ich hoffe, das ist so richtig erklärt.

    VDR darf das Empty() eigentlich nur machen, wenn er selbst danach die Daten von der richtigen Stelle sendet, wo der Stream fortgesetzt werden soll. Evtl. mit ResyncAfterPause?

    Der Patch ist also (ungetestet) wahrscheinlich nicht richtig.

    Ich habe mir mal vor längerer Zeit die Übersicht aus dem Anhang gemacht, da ist der Patch noch nicht drin, würde aber in die pmPause/pmStill Spalte ein DeviceClear bei Forward() und Backward() einfügen, wenn ich es richtig verstehe.

  • Respekt, rell! Du gehst das sehr gründlich an.

    Kannst Du die Tabelle nochmal etwas näher beschreiben? Die waagerechte Zeile oben stellt den aktuellen Playmode dar, in dem man sich gerade befindet. Die linke senkrechte Spalte steht für die Aktion, die dann aus diesem Playmode heraus aufgerufen wird. Korrekt?

    Schwarz ist dann wahrscheinlich noch nicht der Code in vdr-2.7.4, wenn die Tabelle älter ist? Wofür stehen blau, grün und rot jeweils?

    Weder Goto(Current) noch Goto(GetClosestIFrame(Current)) setzen die Wiedergabe genau an der Stelle fort, die vor dem resync angezeigt wurde. Ein kleiner Sprung um eine GOP zurück ist nicht so schlimm, aber wenn das nächste iFrame in der Zukunft liegt, können je nach GOP-Länge 1-2 Sekunden fehlen, und das sieht unschöner aus, als wenn nochmal kurz etwas wiederholt wird. Sowas wie GetLastIFrame wäre daher praktisch.

    Es wird kaum möglich sein, im dvbplayer eine einheitliche Lösung zu finden, die für alle Ausgabedevices passt. Der Versuch, das im Ausgabeplugin dann so anzupassen, dass es harmoniert, ist deutlich aufwändiger, als wenige Codezeilen im dvbplayer für die die individuellen Bedürfnisse anzupassen. Ideal wäre es, wenn das Ausgabeplugin selbst bestimmen könnte, wann vdr ein Clear machen soll und wann ein resync mit Sprung zu welcher Stelle erfolgen soll.

    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

Participate now!

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