Live555 RTSP Server on Android

最近在看 RTSP Server on Android 相關資源,趁現在有空就把它整理整理。

  1. RTSP Server最有名的大概就是 Live555,這套功能還不錯可以支援 .264, .265, .aac, .amr, … 比較重要的是它可以支援 .mkv, .ts (如果Stream這兩種格式都會把Video 跟Audio一同Stream出去, .mkv還會有Subtitle),還有很多格式建議到官網去看一下。

  2. 我找到的另外一個是已經在Android上實現RTSP Server功能的一個Library,叫做libstreaming, 作者叫做fyhertz,他還有另外一個作品叫做spydroid-ipcam, 其功能是把Android手機的Camera跟Microphone透過RTP/UDP發送出去,而libstreaming就是他這套Application的核心library。

(在作者的github網頁中可以找到spydroid-ipcam的source code 跟libstreaming library 還有libstreaming的example1/2/3, 使用者可以使用libstreaming library + libstreaming example1 拼成spydroid-ipcam簡易的樣子)


找好資源後就要自己動工了,如果要讓RTSP Server跑在Android上面並且支援Stream local file的話大概就是兩個選項,在下面一併附上我實作的方法。

  1. 移植Live555到Android上面

    • Live555 Download後解開把source code直接把live下的所有文件放到你想要使用的project下的jni目錄中(需要把project的native support打開並且指定好ndk path)
Console
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Live555project/jni# tree -d
.
├──BasicUsageEnvironment
│   └── include
├── groupsock
│   └── include
├── liveMedia
│   └── include
├── mediaServer
├── proxyServer
├── testProgs
├── UsageEnvironment
│   └── include
└── WindowsAudioInputDevice

檔案太多就不都列出來拉,總之jni下面就是解開live555中live資料夾裡面的東西。

  • 然後要補上Android.mk 跟 一個銜接java 跟 native層的一個.cpp file.

    • Live555的Android.mk在網路上可以找到,連結在此,但是由於他這個版本是2013年的版本,所以使用者使用時必須再加上一些檔案以及mediaServer的部分到LOCAL_SRC_FILE下,再把LOCAL_MODULE的名稱改成 live555, Android.mk一樣是放在jni下。
    • .cpp大概的寫法就是把live555mediaserver.cpp的main function copy把header file寫一寫,然後這隻function name要符合jni的規範讓java層Call的到(ex:Java_com_example_rtspserver_MainActivity_RunRTSPServer…) 然後開始build application,如果你設定都沒有錯應該就會把liblive555.so build出來並且放到project/libs/armeabi/ 下,並且放到.apk中
  • 改libStreaming使之支援Streaming Local file

    • 我改到可以把local file解開然後把其.264部分傳出來,但是這就比較複雜,就不多寫了,主要就是要把URLEncodedUtil那邊看的東西多加local file資訊,這樣Server才會知道Client想要看哪個video,然後要demux該影片,demux這工作可以不用自己來,可以使用ffmpeg或者是Android自帶的api MediaExtractor(Android4.3開始提供),這邊提供如何取出Video的方法:
How to use android MediaExtractor api
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
MediaExtractor mExtractor = new MediaExtractor();
ByteBuffer mTransBuffer = ByteBuffer.allocate(1024*1024*2);
private byte[] mTmpBuf = new byte[1024*1024*2];
String path = video_path/abc.mp4;
mExtractor.setDataSource(path);
int numTrack = mExtractor.getTrackCount();
int h264Track = -1;
for(int i=0;i<numTrack;++i)
{
    MediaFormat format = mExtractor.getTrackFormat(i);
    String mime = format.getString(MediaFormat.KEY_MIME);
    if(mime.contains(video) && mime.contains(avc))
    {
        h264Track = i;
    }
}
if(h264Track!=-1)
{
    mExtractor.selectTrack(h264Track);
    while(true)
    {
        int Size = mExtractor.readSampleData(mTransBuffer,0); // read frame to mTransBuffer
        mTransBuffer.get(mTmpBuf);
        mExtractor.advance(); // go next frame
    }
}

以上就是使用android原生的api去demux一個video file,

使用前提是該container format為android support的format,

在readSampleData後把拿到的mTransBuffer裝到mTmpBuf再把mTmpBuf改裝到在H264Packetizer.cpp中的function Send(),

其Send()原本是把Encode好的BitStream取出然後包裝送出,現在就把他替換成我們Demux之後的video source就可以了.

不過用libstreaming library好像有一些問題在,例如Streaming high bitrate的264會有很容易破圖,可能是有更多的細節需要做更改。

Jun 24th, 2015

Comments