Ich versuche derzeit, Android als Skype-Endpunkt zu verwenden. In diesem Stadium muss ich Video in H.264 kodieren (da es das einzige von Skype unterstützte Format ist) und es mit RTP kapseln, um das Streaming zu ermöglichen.
Anscheinend ist die MediaRecorder
dafür aus verschiedenen Gründen nicht sehr geeignet. Einer ist, weil es die MP4- oder 3GP-Header hinzufügt, nachdem es fertig ist. Ein anderer Grund ist, dass Hardware-Beschleunigung nützlich sein kann, um die Latenz auf ein Minimum zu reduzieren. Deshalb möchte ich die jüngsten Ergänzungen des Frameworks auf niedriger Ebene nutzen, nämlich MediaCodec
, MediaExtractor
usw.
Im Moment plane ich, wie folgt zu arbeiten. Die Kamera schreibt ihr Video in einen Puffer. Der MediaCodec codiert das Video mit H264 und schreibt das Ergebnis in einen anderen Puffer. Dieser Puffer wird von einem RTP-Encapsulator gelesen, der die Stream-Daten an den Server sendet. Hier ist meine erste Frage: Ist dieser Plan für Sie machbar?
Jetzt bin ich schon bei Schritt eins fest. Da alle Dokumentationen im Internet über die Verwendung der Kamera MediaRecorder
verwenden, kann ich keine Möglichkeit finden, ihre Rohdaten vor dem Kodieren in einem Puffer zu speichern. Ist addCallbackBuffer dafür geeignet? Hat jemand einen Link zu einem Beispiel?
Als nächstes kann ich nicht viel Dokumentation über MediaCodec finden (da es ziemlich neu ist). Wer hat ein solides Tutorial?
Zuletzt: irgendwelche Empfehlungen zu RTP-Bibliotheken?
Vielen Dank im Voraus!
UPDATE
Ich war endlich in der Lage, richtige RTP-Pakete aus den h264-Frames zu erstellen. Hier ist, was Sie beachten müssen (es ist eigentlich ganz einfach):
Der Encoder erstellt NAL-Header für jeden Frame. Aber es gibt jedes Bild als h264 Bytestream zurück. Dies bedeutet, dass jeder Rahmen mit drei 0-Bytes und einem 1-Byte beginnt. Sie müssen nur diese Start-Präfixe entfernen und den Frame in ein RTP-Paket einfügen (oder mit FU-As aufteilen).
Nun zu Ihren Fragen:
Ich kann keine Möglichkeit finden, seine Rohdaten vor dem Codieren in einem Puffer zu speichern. Ist addCallbackBuffer dafür geeignet?
Sie sollten camera.setPreviewCallback (...) verwenden und jeden Frame zum Encoder hinzufügen.
Ich kann nicht viel Dokumentation über MediaCodec finden (da es ziemlich neu ist). Wer hat ein solides Tutorial?
Dies sollte eine gute Einführung sein, wie der MediaCodec funktioniert. Ссылка
Zuletzt: irgendwelche Empfehlungen zu RTP-Bibliotheken?
Ich benutze jlibrtp, was den Job erledigt.
Ich weiß noch nichts über MediaCodec oder MediaExtractor, aber ich bin ziemlich vertraut mit MediaRecorder und habe erfolgreich einen RTSP-Server auf Basis von SpyDroid implementiert, der die H264 / AMRNB-Ausgabe von MediaRecorder aufnimmt. Die Grundidee ist, dass der Code ein lokales Socket-Paar erstellt und setOutputFile des MediaRecorder verwendet, um die Ausgabe an einen der Sockets im Paar zu schreiben. Dann liest das Programm den Video- oder Audiostream von dem anderen Socket, parst es in Pakete und wickelt jedes Paket dann in ein oder mehrere RTP-Pakete, die über UDP gesendet werden.
Es ist richtig, dass MediaRecorder die MOOV-Header nach deren Fertigstellung hinzufügt, aber das ist kein Problem, wenn Sie H264-Video im RTP-Format bereitstellen. Im Grunde gibt es einen "mdat" Header am Anfang des Videostreams. Es hat 4 Bytes für die Länge des Headers, gefolgt von den 4 Bytes "mdat". Lesen Sie die Länge, um herauszufinden, wie lange der Header ist, vergewissern Sie sich, dass es der mdat-Header ist, und überspringen Sie dann den Rest der Header-Daten. Von da an erhalten Sie einen Strom von NAL-Einheiten, die mit 4 Byte für die Einheitslänge beginnen. Kleine NAL-Einheiten können in einem einzelnen RTP-Paket gesendet werden, und größere Einheiten werden in FU-Pakete aufgeteilt. Für RTSP müssen Sie außerdem einen SDP-Header bereitstellen, der den Stream beschreibt. SpyDroid berechnet die Informationen im SDP-Header, indem er einen sehr kurzen Film in eine Datei schreibt, und liest dann diese Datei, um den MOOV-Header vom Ende zu extrahieren. Meine App verwendet immer die gleiche Größe, das gleiche Format und dieselbe Bitrate. Daher gebe ich nur eine statische Zeichenfolge ein:
%Vor%Das ist meine Kopfzeile für 640x480x10fps, H264-Video mit 8000/16/1 AMRNB-Audio.
Eine Sache, vor der ich Sie warnen kann: Wenn Sie MediaRecorder verwenden, wird Ihr Preview-Callback nie aufgerufen. Das funktioniert nur im Kameramodus, nicht beim Aufnehmen von Videos. Ich habe keine Möglichkeit gefunden, während der Videoaufnahme in unkomprimiertem Format auf das Vorschaubild zuzugreifen.
Ich empfehle dringend, den Code für SpyDroid zu lesen. Es braucht etwas herumgräbt, aber ich wette, was Sie wollen, ist schon drin.
Was Sie planen, ist definitiv machbar. Sie können einen Camera.PreviewCallback registrieren, der die Bilddaten aufnimmt und in den MediaCodec legt. Sie lesen die Ausgabe und senden sie als RTP. Im Allgemeinen ist es einfach, aber es gibt verschiedene Fallstricke wie undokumentierte Farbräume und unterschiedliche MediaCodec-Verhalten auf verschiedenen Geräten, aber es ist definitiv möglich.
Tags und Links android video-streaming h.264 rtp