Ok, StillPicture sendet anscheinend nur 1 avpkt und wartet auf das frame in einer Schleife. Keine Ahnung, ob das geht. Mal testen.
TrickSpeed - Verständnisfrage
-
-
Nochmal ich. Wenn ich https://ffmpeg.org/doxygen/6.1/gr…362597e467efff3 richtig lese, dürfte ein avcodec_send_packet(context, NULL) dafür sorgen, dass der decoder gepufferte frames ausliefert. Das könnte man dann bei Trickspeed nach jedem gesendetem avpkt nachen?!
-
Das war ja mein 2. Vorschlag. Denke aber dran, dass damit diese Decoder Instanz keine weitete Pakete mehr annimmt.
"the decoder has been flushed, and no new packets can be sent to it (also returned if more than 1 flush packet is sent)"
-
Stimmt
Den Satz habe ich ignoriert. Das wäre die harte Methode, die mich nicht so anlacht...
-
Ich finde den Vorschlag von zillerbaer gut: sende doch einfach das gleiche Packet so lange zum Decoder, bis du das Frame zurück bekommst.
-
Ja, ich werde das morgen ausprobieren, aber nicht über StillPicture sondern mit einer Schleife in VideoDecodeInput - müsste ja auch gehen.
Was würde der decoder eigentlich sagen, wenn man ihm ein packet schickt mit dts=pts=AV_NOPTS_VALUE ?
-
Habe ich nie ausprobiert, ich versuche immer sinnvolle Werte zu verwenden, selbst wenn es heute geht, weiß man ja nie, was nach dem nächsten FFmpeg Update passiert.
-
rell: Du kannst Dir ja mal anschauen, wie jojo61 es in softhdodroid gelöst hat. Die entscheidende Stelle ist m.E. in video.c in der Funktion CodecVideoDecode. Wenn es sich um einen Rückwärts-Trickspeed handelt oder um die Stufen 1, 3 oder 6 (=Spulen, keine Zeitlupe) wird ein reset des Decoders mit Leerung der Buffer ausgeführt. Es findet zudem mittels usleep eine kleine Verzögerung statt, deren Dauer von der Art des Trickmodus abhängig ist. Und irgendwas wird da auch mit der PTS gemacht.
Was mich interessieren würde: Wie gut funktioniert denn bei Euch die aus der Pause heraus aufgerufene Zeitlupe vorwärts und hier insbesondere der Wechsel zurück auf Normalgeschwindigkeit? Hier haben wir uns bislang die Zähne ausgebissen. Es kommt dabei zu Bildsprüngen, weil eine A/V Asynchronität aufgeholt werden muss, die u.a. dadurch entsteht, dass ab Wechsel zu Pause die Audiopakete verworfen werden und der Audio-Buffer gecleart wird. Von vdr kommt an dieser Stelle aber kein Clear. Ich habe versucht, das ähnlich wie beim Spulen mit einem reset des Videodecoders zu lösen, aber es kam nichts brauchbares dabei raus.
Mir ist klar, dass softhdodroid mit seinen amlogic-spezifischen ioctl ganz anders funktioniert, aber vielleicht kannst Du ja trotzdem die eine oder andere Anregung mitnehmen. Generell ist zu sagen, dass Rückwärtsspulen bei h264 Glückssache ist. Es gibt immer wieder Aufnahmen, bei denen das trotzdem nicht funktioniert. Das ist bei softhddevice so, das ist bei softhdodroid so und scheint senderunabhängig zu sein. Wahrscheinlich heißt es deswegen Trickspeed - weil es so tricky ist
-
Kurze Rückmeldung: Ich habe es vermutlich hinbekommen - allerdings mit dem flush. Und zwar schicke ich nach einem erfolgreichen avcodec_send_packet ein NULL pkt, damit ich mit avcodec_receive_frame das Frame sofort zurück bekomme. Danach muss ich noch ein avcodec_flush_buffers ausführen, sonst bekomme ich eof zurück. Erst dann wird bei Trickspeed das nächste avpkt an den decoder geschickt.
Mit verschiedenen pts und dts habe ich es nicht geschafft. Auch nicht, wenn das gleiche avpkt 3x geschickt wird. Ich bekomme dann zwar das mit dem richtigen pts zurück, aber auch nur, weil auch das dritte gesendete den gleichen pts hat. Testweise habe ich danach ein avcodec_send_packet(decoder, NULL) gemacht und dann kommen nämlich nochmal 2 frames mit dem gleichen pts zurück, die der decoder ja noch im Puffer hat.
Jedenfalls braucht der Decoder bei h264 3 avpkt um ein Frame zu liefern - und das Frame ist bei Rückwärtslauf immer das letzte, das geschickt wurde. Keine Ahnung, wie man das umgeht, ohne an ffmpeg ran zu müssen.
Jedenfalls scheint der flush ein gangbarer Weg und ich versuche das mal in einigermaßen sauberen Code zu kriegen.
Mich wundert immer noch, worin der Unterschied liegt zwischen forward und backward mit gefaketem pts liegt. Evtl. wird der pts auch noch intern geprüft. Wenn ich fertig bin, schaue ich mir den ffmpeg code evtl. mal an.
-
rell: Du kannst Dir ja mal anschauen, wie jojo61 es in softhdodroid gelöst hat. Die entscheidende Stelle ist m.E. in video.c in der Funktion CodecVideoDecode. Wenn es sich um einen Rückwärts-Trickspeed handelt oder um die Stufen 1, 3 oder 6 (=Spulen, keine Zeitlupe) wird ein reset des Decoders mit Leerung der Buffer ausgeführt. Es findet zudem mittels usleep eine kleine Verzögerung statt, deren Dauer von der Art des Trickmodus abhängig ist. Und irgendwas wird da auch mit der PTS gemacht.
Genau sowas passiert jetzt auch hier. Hätte ich mal vorher ansehen sollen
Das mit der PTS muss ich mir noch ansehen. Danke für den Tip mit softhdodroid aber da habe ich abgebrochen, als ich zu amlreset gekommen bin. Dachte mit, aha, proprietär und eh ganz anders. Aber dass ein reset einem flush gar nicht so unähnlich ist, da hätte ich auch selber draufkommen können
TrickSpeed aus der Pause kommt als nächstes...
-
jojo61 Wie hast du die "Wartezeit" festgelegt? https://github.com/jojo61/vdr-plu…r/video.c#L1299
-
Wie hast du die "Wartezeit" festgelegt?
Da habe ich einfach durch ausprobieren ermittelt. Allerdings nutzt der softhdodroid ja keinen ffmpeg zum dekodieren. Deswegen ist der vergleich damit eher wie Äpfel mit Birnen. Da wäre ein Vergleich mit dem softhdcuvid wohl besser.
Ich erinnere mich gerade nicht so recht, aber ich schicke da die I-Frames mehrfach durch den ffmpeg dekoder bis ein Frame rauskommt.
-
Was mich interessieren würde: Wie gut funktioniert denn bei Euch die aus der Pause heraus aufgerufene Zeitlupe vorwärts und hier insbesondere der Wechsel zurück auf Normalgeschwindigkeit? Hier haben wir uns bislang die Zähne ausgebissen. Es kommt dabei zu Bildsprüngen, weil eine A/V Asynchronität aufgeholt werden muss, die u.a. dadurch entsteht, dass ab Wechsel zu Pause die Audiopakete verworfen werden und der Audio-Buffer gecleart wird. Von vdr kommt an dieser Stelle aber kein Clear. Ich habe versucht, das ähnlich wie beim Spulen mit einem reset des Videodecoders zu lösen, aber es kam nichts brauchbares dabei raus.
Ich weiss jetzt nicht, ob das auf eurer Hardware anders ist, aber auf "normaler" Hardware habe ich das bereits 2015 gefixt.
PostRE: Soft-Start bei softhddevice
Ein neuer Patch für die Fehlerbehandlung vom recover nach dem underrun in AlsaPlayRingbuffer().
Gelegentlich hat AudioUsedModule→FlushBuffers(); unerwünschte Nebenwirkungen.
Der Unterschied ist, für erfolgreichen recover mit return 0 raus zu gehen statt mit continue.
Das passt dann auch besser zu den Kommentaren.jrieDecember 2, 2015 at 2:37 PM jojo61 hat für seine Forks einen Stand benutzt, wo das (und andere wichtige Fixe) nicht drin war.
Mit return 0; statt continue; braucht man die ganzen workarouds nicht mehr.
Der Fix ist eher unintuitiv, da normalerweise in den Beispielen immer continue; steht, aber durch die ganzen Verschachtelungen im Audio Code ist das so nötig.
-
Bringt leider keine Veränderung.Das Problem tritt auch nicht beim einfachen Wechsel von Pause zu Play und zurück auf, sondern immer nur, wenn dazwischen eine Zeitlupe vorwärts gestartet wurde.
-
Ich habe den aktuellen Stand mal ins git geschoben: https://github.com/rellla/vdr-plu…/trickspeedV02/
Das Grundgerüst sollte funktionieren, aber die Tests mit verschienenen TrickSpeed/Pause/Play/Codec-Kombinationen fehlen noch - auch wie das auf anderen Devices wie dem RPi aussieht. Wenn da alles geht, schau ich mir die Übergänge an.
-
Klappt schonmal nicht ganz richtig, da muss ich nochmal ran
Mein Ansatz war viel zu kompliziert. Ich habe das Frame während der Darstellung vervielfacht. Das muss ich schon vorher machen und den display thread in Ruhe lassen...
-
Das Problem tritt auch nicht beim einfachen Wechsel von Pause zu Play und zurück auf, sondern immer nur, wenn dazwischen eine Zeitlupe vorwärts gestartet wurde.
Gerade getestet: das tritt auch bei softhddevice auf.
-
ugly fix for Pause -> SlowForward -> Play:
https://github.com/j1rie/vdr-plug…48419583ee423e9
Noch nicht auf Nebenwirkungen getestet, aber löst das Problem.
Das SlowForward löst ein Mute aus, das verursacht AudioFlushBuffers(), das setzt AudioVideoIsReady auf 0, deswegen spielt dann kein Audio mehr beim Play(). Wenn man bei Beendigung das Trickspeeds AudioVideoIsReady auf 1 setzt, kommt Ton.
-
Oder so:
Code
Display Moreint oldspeed; ... void cSoftHdDevice::TrickSpeed(int speed, bool forward) { Debug(3, "[softhddev]%s: %d %d\n", __FUNCTION__, speed, forward); oldspeed = speed; ::TrickSpeed(speed); } ... void cSoftHdDevice::Play(void) { Debug(3, "[softhddev]%s:\n", __FUNCTION__); printf("softhddev Play\n"); if (oldspeed ==2 || oldspeed == 4 || oldspeed == 8) { Debug(3, "[softhddev] Clear: Play after SlowForward\n"; ::Clear(); } cDevice::Play(); ::Play(); }
Das gibt aber einen kleinen Sprung.
-
Wenn man sich mit GetIndex() die Stelle holt, wo man gerade ist und dann mit Goto() dahin springt, müsste es gehen (Goto() müsste man auch noch in VDR's player.h einbauen, GetIndex() gibts da schon).
Mein C++ ist aber zu schlecht dafür.
-
Participate now!
Don’t have an account yet? Register yourself now and be a part of our community!