有點晚了,但我認爲這是一個很好的問題,它還沒有一個好的答案。
如果你想從Android設備流式傳輸相機和麥克風,你有兩個主要的選擇:Java或NDK實現。
Java實現。
我只想提到這個想法,但基本上它是基於這些標準Real-Time Streaming Protocol Version 2.0和RTP Payload Format for H.264 Video在java中實現RTSP服務器和RTP協議。這項任務將會非常艱鉅。但是如果你正在做PhP,那麼爲Android設置一個不錯的RTSP Java lib可能會很好。
NDK實施。
這是替代包括各種解決方案。主要思想是在Android應用程序中使用強大的C或C++庫。對於這個例子,FFmpeg。該庫可以針對Android進行編譯,並可以支持各種體系結構。 這種方法的問題是,您可能需要了解Android NDK,C和C++來完成此操作。
但有一個選擇。你可以包裝c庫並使用FFmpeg。但是如何?
例如,使用FFmpeg Android,它使用x264,libass,fontconfig,freetype和fribidi編譯並支持各種體系結構。但是,如果您想實時流式傳輸,則需要處理文件描述符和輸入/輸出流,但仍難以編程。
從Java編程的角度來看,最好的選擇是使用JavaCV。 JavaCV使用來自包括計算機視覺的常用包裝的庫:(OpenCV,FFmpeg等,並提供實用工具類,使其功能更容易在Java平臺上使用,包括(安卓當然)
JavaCV也來了。硬件加速的全屏圖像顯示(CanvasFrame
和GLCanvasFrame
),易於使用的方法在多個內核上並行執行代碼(Parallel
),用戶友好的相機和投影儀的幾何和顏色校準(GeometricCalibrator
,) ,特徵點的檢測和匹配(ObjectFinder
),一組實現投影機 - 照相機系統的直接圖像對齊的類(主要爲GNImageAligner
,ProjectiveTransformer
,ProjectiveColorTransformer
,ProCamTransformer
和ReflectanceInitializer
),斑點分析包(Blobs
)以及JavaCV
類中的其他功能。有些類也有OpenCL和OpenGL的對手,他們的名字與CL
結束或開始GL
,即:JavaCVCL
,GLCanvasFrame
等
但如何才能使用此解決方案?
這裏我們有一個使用UDP進行流式傳輸的基本實現。
String streamURL = "udp://ip_destination:port";
recorder = new FFmpegFrameRecorder(streamURL, frameWidth, frameHeight, 1);
recorder.setInterleaved(false);
// video options //
recorder.setFormat("mpegts");
recorder.setVideoOption("tune", "zerolatency");
recorder.setVideoOption("preset", "ultrafast");
recorder.setVideoBitrate(5 * 1024 * 1024);
recorder.setFrameRate(30);
recorder.setSampleRate(AUDIO_SAMPLE_RATE);
recorder.setVideoCodec(AV_CODEC_ID_H264);
recorder.setAudioCodec(AV_CODEC_ID_AAC);
這部分代碼顯示瞭如何初始化稱爲記錄器的FFmpegFrameRecorder對象。該對象將捕獲並編碼從相機獲取的幀和從麥克風獲得的樣本。
如果你想在同一個Android應用程序中捕捉預覽,那麼我們需要實現一個CameraPreview類,這個類將轉換從相機提供的原始數據,它將爲FFmpegFrameRecorder創建預覽和框架。
請記住用您想要發送流的pc或設備的IP替換ip_destination。例如,端口可以是8080。
@Override
public Mat onCameraFrame(Mat mat)
{
if (audioRecordRunnable == null) {
startTime = System.currentTimeMillis();
return mat;
}
if (recording && mat != null) {
synchronized (semaphore) {
try {
Frame frame = converterToMat.convert(mat);
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
recorder.record(frame);
} catch (FFmpegFrameRecorder.Exception e) {
LogHelper.i(TAG, e.getMessage());
e.printStackTrace();
}
}
}
return mat;
}
此方法顯示了onCameraFrame
方法獲得來自攝像機的墊(圖片)的執行,並將其轉換爲一幀,並由FFmpegFrameRecorder對象記錄。
@Override
public void onSampleReady(ShortBuffer audioData)
{
if (recorder == null) return;
if (recording && audioData == null) return;
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
LogHelper.e(TAG, "audioData: " + audioData);
recorder.recordSamples(audioData);
} catch (FFmpegFrameRecorder.Exception e) {
LogHelper.v(TAG, e.getMessage());
e.printStackTrace();
}
}
同與所述音頻的audioData
爲ShortBuffer
對象,這將是由FFmpegFrameRecorder記錄器。
在PC或設備目標中,您可以運行以下命令來獲取流。
ffplay udp://ip_source:port
ip_source
是流式傳輸相機和麥克風流的智能手機的IP地址。端口必須是相同的8080.
我在我的github資源庫中創建了一個解決方案:UDPAVStreamer。
祝你好運
你爲什麼使用ffmpeg解碼?使用內置的MediaPlayer對象 –
您是否嘗試過使用live555通過RTSP傳輸ffmpeg的輸出?另外,不應該ffmpeg探測流,並找出流信息本身? – Shark
我認爲Aviad有它的真相。你甚至怎麼知道相機產生的視頻格式? –