Meine Trickspeed Lösung habe ich eingecheckt und mit dem Patch von oben bin ich jetzt nach ein paar Tests erstmal sehr zufrieden.
Bis auf die angezeigte Zeit, die zuerst rennt und sich nach kurzer Zeit erst wieder fängt. Habt ihr das auch?
Meine Trickspeed Lösung habe ich eingecheckt und mit dem Patch von oben bin ich jetzt nach ein paar Tests erstmal sehr zufrieden.
Bis auf die angezeigte Zeit, die zuerst rennt und sich nach kurzer Zeit erst wieder fängt. Habt ihr das auch?
Folgende Abfolge macht aber auch Probleme:
Play->Pause->SlowForward->Pause->Play
Habt ihr das mal getestet?
Kann ich für softhdodroid bestätigen.
Für play-pause-slow forward play sieht mein Fix etwas anders aus. Resync ohne GoTo sieht sauberer aus.
Was softhddevice angeht, kann ich die Probleme nicht bestätigen, da klappt bei mir alles. Warum das bei jrie anders ist, ist noch unklar.
Kann ich für softhdodroid bestätigen.
Für play-pause-slow forward play sieht mein Fix etwas anders aus. Resync ohne GoTo sieht sauberer aus.
Was softhddevice angeht, kann ich die Probleme nicht bestätigen, da klappt bei mir alles. Warum das bei jrie anders ist, ist noch unklar.
D.h. dem hier?
--- dvbplayer.c 2024-10-12 13:32:46.000000000 +0200
+++ dvbplayer.c.NEU2 2024-10-24 01:20:03.152487970 +0200
@@ -746,6 +746,8 @@ void cDvbPlayer::Play(void)
if (!(DeviceHasIBPTrickSpeed() && playDir == pdForward))
Empty();
}
+ if (playMode == pmSlow && playDir == pdForward)
+ resyncAfterPause = true;
DevicePlay();
playMode = pmPlay;
playDir = pdForward;
Display More
Dann vergleiche ich die mal.
Hast du am softhd* auch was gepatcht?
Bei mir sieht das so aus:
--- dvbplayer.c.orig 2024-10-26 18:26:01.000000000 +0200
+++ dvbplayer.c 2024-10-30 15:52:52.000000000 +0100
@@ -740,19 +740,26 @@
void cDvbPlayer::Play(void)
{
+ bool resyncAfterSlowForward = false;
if (playMode != pmPlay) {
LOCK_THREAD;
if (playMode == pmStill || playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
if (!(DeviceHasIBPTrickSpeed() && playDir == pdForward))
Empty();
}
+ if (playMode == pmSlow && playDir == pdForward) {
+ resyncAfterPause = true;
+ resyncAfterSlowForward = true;
+ }
DevicePlay();
playMode = pmPlay;
playDir = pdForward;
if (resyncAfterPause) {
- int Current, Total;
- if (GetIndex(Current, Total, true))
+ int Current, Total;
+ if (GetIndex(Current, Total, resyncAfterSlowForward ? false : true)) {
+ Empty();
Goto(Current);
+ }
resyncAfterPause = false;
}
}
Display More
GoTo verwende ich also doch, ermittle aber den Index bei einer vorherigen "Zeitlupe vorwärts" nicht mit SnapToIFrame
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
// Returns the current and total frame index, optionally snapped to the
// nearest I-frame.
Ob der zusätzliche Empty()-Aufruf bei jedem resyncAfterPause notwendig ist oder nicht auch von resyncAfterSlowForward abhängig sein sollte, muss ich mir nochmal anschauen.
softhdodroid hat weiter keine Änderungen. void Mute() enthält
QuoteMeine Vermutung: softhddevice setzt durch das DeviceMute SkipAudio, was dem VDR durch die Rückgabe von size in PlayAudio() signalisiert, dass die Audiopakete angenommen worden sind. Die landen aber nicht im Ringbuffer. Bei Mute ist das schon richtig, weil die PTS ja weiterlaufen soll und dem VDR vorgetäuscht wird, dass die Audiopakete verarbeitet wurden. Bei Trickspeed ist das aber schlecht.
Ja, das dürfte eine zutreffende Analyse sein. Was ich noch nicht sicher weiss: was ist mit StreamFreezed = 1;, das in Freeze gesetzt wird? Ich glaube das bleibt auch bei der Zeitlupe so. Das führt dann dazu, dass PlayAudio return 0 zurückgibt (wenn SkipAudio nicht gesetzt ist, was zu return size führen würde).
Besser wäre es, wir finden einen anderen Weg den alsa-Ton stumm zu schalten. Aber das scheint wohl nur über den alsamixer zu gehen und es dürfte schwierig sein, das in C++ mit einem für alle Umgebungen passenden Code zu machen (?)
Ohne SkipAudio und ohne AudioFlushBuffers in Mute funktioniert alles wie es soll- aber die Zeitlupe bleibt nach einiger Zeit stehen, weil vdr das Senden weiterer Videopakete einstellt. Da PlayAudio dann 0 zurückgibt, unterstellt vdr wohl, dass das device auch nicht mehr in der Lage ist, Videopakete anzunehmen. siehe auch RE: Rückgabewert von cDevice::Poll wird ignoriert
virtual int PlayAudio(const uchar *Data, int Length, uchar Id);
///< Plays the given data block as audio.
///< Data points to exactly one complete PES packet of the given Length.
///< Id indicates the type of audio data this packet holds.
///< PlayAudio() 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.
Das Problem ist PlayAudio, das dem VDR entweder sagt, alles OK, bitte nächstes Paket schicken (return size) oder bitte nochmal (return 0). Es dürfte immer nur das zum video passende audio annehmen, aber wenn buffering im Spiel ist, wird das nicht klappen. Ich kriegs im Kopf noch nicht zusammen, wie das Plugin das alleine hinkriegen könnte. Falls das überhaupt geht.
Besser wäre es, wir finden einen anderen Weg den alsa-Ton stumm zu schalten. Aber das scheint wohl nur über den alsamixer zu gehen und es dürfte schwierig sein, das in C++ mit einem für alle Umgebungen passenden Code zu machen (?)
Aber selbst dann kommen von VDR mit PlayAudio Daten, wo das Plugin entscheiden muss, ob es sie verweigert, verwirft, puffert oder ausgibt. Ich glaube, das Plugin hat (ohne großen Aufwand) keine Chance - wenn überhaupt -, das zu handeln. Wenn ein minimaler Eingriff in VDR core akzeptabel ist (siehe Beispiele oben), wäre das m.E. der einfachere und universalere Weg...
Es dürfte immer nur das zum video passende audio annehmen, aber wenn buffering im Spiel ist, wird das nicht klappen.
Wenn bei jedem neuen Video das Audio vor dem Video weggeschmissen wird (wie in AudioVideoReady()), könnte das gehen, oder?
Besser wäre es, wir finden einen anderen Weg den alsa-Ton stumm zu schalten.
Dafür gibt es AudioSetVolume().
Ich mache mal hier weiter. Ist nicht auf Herz und Nieren getestet und auch Feintuning ist sicher möglich, aber sowas in der Art müsste funktionieren:
Mit ein paar Fixes läuft es eigentlich ganz vernünftig, so dass ich es mal eingecheckt habe: https://github.com/rellla/vdr-…/commits/drm-atomic-gles/
Ein paar gewürgte Hacks sind noch versteckt, aber das muss ich mir später mal ansehen.
Im Übereifer habe ich Rpi5 + Amlogic nicht getestet und da hat sich ein Bug eingeschlichen. Ich habe bisher nur den Hardwaredecoding Pfad verfolgt, Softwaredecoding funktioniert nicht, was zu segfaults beim playback und trickspeed führt. Ich weiß, woran es liegt, aber sollte jemand softhddevice-drm-gles für den RPI nutzen, muss er wieder ein paar Commits zurückspulen und noch etwas warten... sorry
Für softhdodroid präferiere ich im Moment eher einen Patch in dvbplayer.c, weil das einfacher umzusetzen ist und wir dann ja eh in einem proprietären System (amlogic-eigene Treiber) unterwegs sind.
Ich habe meinen Patch nochmal überarbeitet und auch das Play - Pause - Slow Fordward - Pause - Play - Problem integriert. Die Verwendung von GetClosestIFrame statt GetNextIFrame liefert ein deutlich besseres Ergebnis.
root@CoreELEC ~/vdr-2.7.3 # diff -ur dvbplayer.c.orig dvbplayer.c
--- dvbplayer.c.orig 2024-10-26 18:26:01.000000000 +0200
+++ dvbplayer.c 2024-11-17 11:38:31.000000000 +0100
@@ -261,6 +261,7 @@
cFrame *playFrame;
cFrame *dropFrame;
bool resyncAfterPause;
+ bool resyncAfterSlowForward;
void TrickSpeed(int Increment);
void Empty(void);
bool NextFile(uint16_t FileNumber = 0, off_t FileOffset = -1);
@@ -746,14 +747,20 @@
if (!(DeviceHasIBPTrickSpeed() && playDir == pdForward))
Empty();
}
+ if (playMode == pmSlow && playDir == pdForward) {
+ resyncAfterPause = true;
+ resyncAfterSlowForward = true;
+ }
DevicePlay();
playMode = pmPlay;
playDir = pdForward;
if (resyncAfterPause) {
- int Current, Total;
- if (GetIndex(Current, Total, true))
- Goto(Current);
+ int Current, Total;
+ if (GetIndex(Current, Total, true)) {
+ Goto(resyncAfterSlowForward ? index->GetClosestIFrame(Current) : Current);
+ }
resyncAfterPause = false;
+ resyncAfterSlowForward = false;
}
}
}
@@ -797,6 +804,10 @@
// run into pmPause
case pmStill:
case pmPause:
+ if (playDir == pdForward){
+ resyncAfterPause = true;
+ resyncAfterSlowForward = true;
+ }
DeviceMute();
playMode = pmSlow;
playDir = pdForward;
Display More
rell: Ich glaube, Deinen ClearAudio-Aufruf in Mute kannst Du rausnehmen:
Der kommt ja wegen SkipAudio nie zur Ausführung:
Stimmt, danke für den Hinweis. Da gibts noch einiges, was sauberer werden könnte. Ichvwae erstmal um das funktionierende Trickspeed froh. Ich habe bisher auch noch keine Probleme (auf Rockchip) mit h264 Material festgestellt - bin aber meine Sammlung auch noch nicht durch.... weil ja schon öfter die Rede davon war, dass Trickspeed bei h264 oftmals ein Glücksspiel ist.
Jetzt muss ich allerdings erst noch Rpi wieder geradebiegen. So, wie Trickspeed mit den framebuffer-arrays jetzt gelöst ist, gefällt es mir nicht. Etwas hakelig... und dadurch kam der Fehler auch.
Wenn dvbplayer.c den Patch kriegt, habe ich nichts dagegen. Ansonsten halt im Plugin.
Meine Arbeit am trickspeed ist (hoffentlich) erstmal soweit abgeschlossen. Man könnte es sicher noch schöner machen, aber das kommt dann im Anschluß.
Getestet habe ich rockchip und rpi4. rpi zwar nicht exzessiv, aber das hat ganz gut ausgesehen.
Ich habe noch das kleine Problem, dass beim Wechsel von/in trickspeed/play/pause manchmal ein schwarzes Bild geschickt wird, aber das hat mit softhddevice-drm-gles zu tun. Problem ist identifiziert und muss "nur" noch behoben werden.
Zur Info, den Patch für VDR brauche ich nicht.
Don’t have an account yet? Register yourself now and be a part of our community!