2016-08-09 52 views
1

Ich habe ein Problem mit RTMP Streaming von Android-Oberfläche zu einer Client-Anwendung. Meine Lösung hat eine sehr große Latenz, weil meine Oberfläche keine Frames 60 Mal pro Sekunde produziert, sondern sie jederzeit (in 30 Sekunden zum Beispiel) produzieren kann. Ich möchte also jeden neu produzierten Frame sofort dem Kunden zeigen.Streaming-Video von Android-Oberfläche

Android drückt jeden Frame, es sieht gut aus. Client-App (jwplayer oder vlc) empfängt es, aber es wartet auf etwas. Es zeigt Video nur nach dem Empfang einer Anzahl von Frames. Aber ich muss jeden eingehenden Frame auf der Client-Seite sehen, wenn er gerade empfangen wurde.

Wie es jetzt funktioniert: Ich habe ein Surface Objekt, erhalten von MediaCodec Klasse. MediaCodec ist für h264-Videokodierung eingestellt.

MediaCodec mEncoder; 

..... 

MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height); 
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); 
format.setInteger(MediaFormat.KEY_BIT_RATE, videoBitrate); 
format.setInteger(MediaFormat.KEY_FRAME_RATE, videoFramePerSecond); 
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iframeInterval); 

try { 
    mEncoder = MediaCodec.createEncoderByType("video/avc"); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
mSurface = mEncoder.createInputSurface(); 
if (mSurfaceCallback!=null) 
    mSurfaceCallback.onSurfaceCreated(mSurface); 
mEncoder.start(); 

Manchmal Android ist an die Oberfläche. Ich kann die Geschwindigkeit dieser Zeichnungen nicht kontrollieren. Ich kann auch nichts auf diese Oberfläche malen. Wenn sich etwas an der Oberfläche ändert, erzeugt MediaCodec einen neuen byteBuffer mit h264-Rahmen. Ich sende diesen Rahmen von rtmp.

Auf einer Client-Seite habe ich HTML-Seite mit jwplayer

<pre id="myElement"></pre> 
<script> 
var playerInstance = jwplayer("myElement"); 
playerInstance.setup({ 
file:"rtmp://127.0.0.1:1935/live/stream", 
height: 800, 
width: 480, 
autostart: true, 
controls: false, 
    rtmp: { 
     bufferlength: 0.1 
    } 
}); 
</script> 

Ich habe versucht iframeInterval, fps die Codierung zu ändern, bufferLength .. Nichts ist wirklich hilfreich.

Gibt es irgendeine Möglichkeit, ankommende Frames sofort anzuzeigen?

Antwort

1

Was meinst du? Wenn ich richtig verstanden habe - Sie haben: vlc (Client) ---- rtmp Protokoll ---- android (Produzent) Sie kodieren Video von etwas (möglicherweise Kamera) mit MediaCodec und in VLC gibt es Zeit Latenz? Recht?

Zuerst - was verwenden Sie - direkten Eingangspuffer oder MediaCodec.Callback()? In Callback - Sie können jeden Frame in OnOutputBufferAvailable überprüfen und Zeit von einem Frame zum anderen berechnen - dies wird Ihnen zeigen - ist dieses Problem auf der Android-Seite.

Dann können Sie versuchen Rahmen transef Problem

  1. Sie Wireshark lösen können Rahmen Sendezeitpunkt und Chek bestimmen - sein kann, das ist Netzwerkproblem
  2. Than - vlc und die anderen Spieler versuchen zu füllen einige interne Puffer und erst danach starten, um Video zu zeigen. Versuchen Sie, den vlc-Puffer auszuschalten (https://forum.videolan.org/viewtopic.php?t=40408). Dann - es ist üblich, dass VLC auf IDR-Frame wartet. Sie können das Intervall für das Senden von IDR-Rahmen im Code festlegen

    format.setInteger (MediaFormat.KEY_I_FRAME_INTERVAL, iframeInterval); iframeInterval in Sekunden (Versuch 1 Sekunde eingestellt) (dies wird Streaming-Größe erhöhen)

Sorry für meinen schlechten Englisch

0

Sie können hoffentlich Video-Frames mit konstanter Geschwindigkeit erzeugen, sogar mehr als 20 fps um ein flüssiges Video mit akzeptabler Latenz zu erzeugen. Der h264-Encoder verarbeitet ein stabiles Bild (eines, das sich einmal in ~ 30 Sekunden ändert) und wenn keine Änderung erfolgt, wird die Bildgröße minimal sein.