MediaCodec KEY_FRAME_RATE scheint, um ignoriert zu werden
Ich versuche, ändern Sie die Quelle für screenrecord in android 4.4 und niedriger der erfassten frame-rate, aber egal welchen Wert ich in:
format->setFloat("frame-rate", 5);
das Ergebnis ist immer das gleiche ( eine sehr hohe frame rate )
Ist der encoder ignorieren diese Eigenschaft ?
wie kann ich die Framerate ?
- Es sieht so aus, der Wert wird nur verwendet für das schreiben von ein paar header-info in den resultierenden mp4-Datei, nicht für die Kontrolle der capture rate. Für, die, würden Sie ändern müssen, um den loop-encoder und die Bilder fallen entsprechend.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
frame-rate
Wert nicht ignoriert, aber es nicht tun, was Sie wollen.Die Kombination von
frame-rate
undi-frame-interval
bestimmt, wie Häufig I-frames (auch als "sync-frames") angezeigt, in die kodierte Ausgabe. Die frame-rate-Wert könnte auch eine Rolle spielen bei der Erfüllung derbitrate
Ziel auf einigen Geräten, aber ich bin nicht sicher, dass (siehe z.B. dieser Beitrag).Den
MediaCodec
encoder nicht drop frames. Wenn Sie möchten, um die Framerate zu reduzieren, müssen Sie so tun, indem Sie senden weniger frames zu.Den
screenrecord
Befehl nicht "Probe" den Bildschirm an einer fixen frame-rate. Anstatt jedes frame erhält er von der Oberfläche compositor (SurfaceFlinger) an die encoder, mit einem entsprechenden Zeitstempel. Wenn screenrecord erhält 60 frames pro Sekunde, müssen Sie mit 60 fps-Ausgabe. Wenn es erhält 10 Bilder in schneller Folge, gefolgt von nichts für 5 Sekunden, gefolgt von ein paar mehr, Sie haben genau das in die Ausgabe-Datei.Können Sie ändern
screenrecord
frames drop, aber man muss ein bisschen vorsichtig sein. Wenn Sie versuchen, reduzieren Sie die maximale Bildrate von 60fps auf 30fps fallen für jeden zweiten frame, laufen Sie Gefahr, dass in einem "frame0 - frame1 - long_pause - frame2" - Sequenz werden Sie drop-frame1, und das video wird halt auf frame0 stattdessen zeigt ein nicht-ganz-komplett-animation. Sie müssen also Puffer eines Rahmens, und dann codieren oder drop-frame N-1, wenn der Unterschied in der Präsentation mal zwischen, dass und Rahmen N von ~17ms.Der schwierige Teil ist, dass
screenrecord
in seiner Standard-Betriebsart, leitet die frames an den encoder, ohne Sie zu berühren, so dass alle Sie sehen, ist die codierte Ausgabe. Sie können nicht willkürlich droppen einzelne frames der codierten Daten, so dass Sie wirklich wollen, um zu verhindern, dass die encoder sehen, wie Sie in den ersten Platz. Wenn Sie die screenrecord v1.1 Quellen können Sie Tippen Sie in "overlay" - Modus, verwendet für--bugreport
zu haben, um die frames passierenscreenrecord
auf Ihrem Weg zum encoder.In mancher Hinsicht könnte es einfacher sein, einen Beitrag zu schreiben-Prozessor, verringert sich die frame rate. Ich weiß nicht, wie viel Qualität würde verloren gehen, wenn decoding und re-encoding des Videos.
Update: für ein Beispiel wie es grob, fügen Sie diese zu
processFrame_l()
:Hinweis: dieser kommt nach
updateTexImage()
erwirbt der nächste Puffer, und überspringt den Anruf zuswapBuffers()
, die legt den Puffer an den video-encoder.updateTexImage()
wenn nichts neues da ist und es wird nur das Vorherige Bild wieder, so können Sie nur brauchen, um einen timer off gehen, wenn keine neuen frames angekommen sind, und legt dem vorherigen frame, wenn das nicht so gewesen.swapBuffers()
. Der code inprocessFrame_l()
Riegel der neue Rahmen ist, macht es, und swaps. Sie konnte Spaltung, ändern der main loop aufrufenupdateTexImage()
wenn ein neuer frame verfügbar ist, aber nicht alles zeichnen; dann jeden 33.3 ms Sie aufwachen und tun die render + swap. Diese Ausbeute video auf eine Konstante 30fps, die übermittlung der gleiche frame immer wieder, wenn das system im Leerlauf ist. Wenn Sie das nicht wollen, können Sie fügen Sie ein "habe ich eingereicht, dieser Rahmen" zu testen, die zurückgesetzt werden, wenn ein neues Bild kommt.swapBuffers()
als "senden, was ich gerade gezogen, um den video-encoder". Wenn Sie nur anrufenswapBuffers()
ohne Zeichnung alles, was Sie werden unglücklich sein.updateTexImage()
bedeutet "nehmen, was das neueste, was wir von der compositor ist, und legen Sie es in einer GLES textur". Wenn man sich So anschautprocessFrame_l()
können Sie sehen, dass es greift das neue Bild (oder die alten Rahmen, wenn nichts neues erschienen), macht es mit etwas text, und dann sendet es an den video-encoder.setDisplayProjection()
. Sie können deaktivieren Sie die automatische Drehung zum Gerät in den Einstellungen, aber ich weiß nicht, ob das eine option für Sie.