Beiträge von rell

    So, auch ich bin wieder einen Schritt weiter. FFMpeg hat leider keine decodierten frames zurückgegeben. Das lag daran, dass ffmpeg durch das vorherige replay die Anzahl der benötigten frames - bevor das fertige ausgegeben wurde - hochgesetzt hat, da schon mal B-Frames aufgetaucht sind. Macht Sinn. Macht aber keinen Sinn, wenn nur I-Frames kommen. ffmpeg liefert dann "no picture", ergo kein frame.

    Wenn ich den Decoder aber mit dem ersten gesendeten Trickspeed schließe und einmalig neu öffne, gibt es den ffmpeg-internen Zähler noch nicht, und ich kann dann auch ganz normal packets senden und frames abrufen, ohne auf die gesendet Anzahl der packets zu achten. Den flush nach einem erhaltenen Frame brauchts trotzdem - zumindest beim Rücklauf. Mal sehen, wie ich das alles zusammenbringe. Danach schaue ich mir an, was ihr oben so herausgefunden habt.

    Ich denke, ich habs jetzt hinbekommen, zumindest ohne multispeed.

    Für meine 3 Beispielstreams sieht es folgendermaßen aus:


    MPEG2 576i: send 1 avpkt, send flush packet, receive frame, flush buffers

    H264 720p: send 1 avpkt, send flush packet, receive frame, flush buffers

    H264 1080i: send 2 avpkts, send flush packet, receive frame, flush buffers


    Jetzt wäre nur noch die Frage, wie ich herausfinden kann, dass ich bei dem H264 1080i stream 2 Pakete senden muss.

    Momentan greife ich die coded_height ab und treffe die Entscheidung damit. Das funktioniert aber nur, wenn sicher ist, dass alle Streams dem oben beschriebenen Schema folgen!?


    Alternativ könnte ich mir avpkt->data abgreifen und solange frames senden, bis wieder eines mit

    Code
    0x00 0x00 0x01 0x09 0x10

    kommt?

    Ich bin noch am Kämpfen mit dem ffmpeg decoder. Alle Versuche, das sauber hinzukriegen, sind bislang gescheitert.

    Ich möchte ein avpkt senden, von mir aus auch mehrfach, wenns hilft oder einen flush schicken und dann auf das Frame warten. Das klappt teilweise auch.


    Bei 1080i, z.B. AnixeHD habe ich aber Probleme und habe mir mal die avpkt->data angesehen. Hier wäre mal so ein Beispielablauf, wenn ich keine avpkt doppelt schicke, sondern nur den decoder fülle und nach jedem send versuche, das frame zu bekommen. Kann mir jemand auf die Sprünge helfen, was es z.B. mit den ersten beiden Paketen auf sich hat, die nur 20ms auseinander sind? Den avpkt->pts und die ersten 10 bytes von avpkt->data gebe ich aus.

    Gehören .311 und .331 zusammen und ich brauche beide für ein frame? Bin in den Bitstream noch nicht eingestiegen...

    Jedenfalls ist es so, dass das erste avpkt wieder als frame kommt, die anderen 5 gehen unter, weil oben nach dem receive ein decoder flush stattfindet....

    Bei meinem Thema bin ich etwas weiter. Ich vervielfache jetzt bereits die ankommenden avpkt und schicke die clone so oft zum decoder, wie es TrickSpeed vorgibt.

    Ich probiere gerade aus, wieviel avpkt der decoder bei mpeg2/h264 i/p benötigt, um ein frame auszuwerfen. Wenn zuviel gesendet werden, korrigiert der decoder die Reihenfolge und das ist bei rückwärts schlecht. Wenn gesendete avpkt Anzahl und Zeitpunkt des flush passen, scheint es zu funktionieren. Ich muss es jetzt nur noch zusammenkriegen.

    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...

    Der einzige Grund, warum ich meinen Eintrag nicht aktualisert habe, ist, dass ich nicht drangedacht habe und auch nicht aufdringlich genug daran erinnert wurde. Jetzt ist er wieder aktuell.


    Vielleicht wäre es eine Möglichkeit, den Counter so zu lassen, wie er ist und stattdessen an verschiedensten Stellen "Erinnerungen" einzubauen. Z.B. analog zum FB-Anlernen beim ersten Start oder als monatliche OSD-Message, die man auf Dauer abstellen kann oder sich wieder erinnern lassen kann. Kann zwar auch nervig sein, aber diesen einen Klick braucht man ja auch bei der Nach-Hause-Telefonieren-Methode, aber der Datenschutz wäre erledigt.

    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...

    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.

    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 ?

    Ja, könnten. Die Frage ist nur, obs da geht. Habe mir StillPicture noch nicht angeschaut, aber die Vorhehensweise, wie avpkts an ffmpeg geschickt werden und das frame abgeholt wird dürfte ja gleich sein. Der VideoRenderFrame bzw. Frame2Display Teil funktioniert ja bereits sobald es ein fertiges Frame gibt. Es hakt "nur" daran, dass CodecVideoReceiveFrame kein Frame mehr liefert sondern ein ständiges EAGAIN, obwohl mit CodecVideoSendPacket erfolgreich weiter avpkt geschickt werden. Daher vermute ich den Fehler an ffmpeg und pts/dts...