Android上启动一个轻量级RTSP服务,让Android终端像网络摄像头一样提供个外部可供RTSP拉流的服务,在内网小并发又不希望部署单独流媒体服务的场景下非常适用,在Android终端实现这样的流媒体服务,决定了,只能是轻量级的服务。可以通过集成第三方库或编写自定义的RTSP服务器代码来实现这一功能。
今天我们介绍两种方案,一种是GStreamer,另外一种,大牛直播SDK的SmartRtspServer。
在Android平台上使用GStreamer来启动RTSP服务涉及几个关键步骤,包括配置GStreamer环境、编写GStreamer管道(pipeline)以及集成到Android应用中。
GStreamer管道定义了媒体数据的处理流程。对于RTSP服务,你需要创建一个能够捕获媒体(如摄像头视频)、编码它,并通过RTSP服务器发送的管道,GStreamer的特点。
一个基本的RTSP服务器管道示例代码如下:
GstElement *pipeline, *src, *enc, *sink;
/* 初始化GStreamer */
gst_init(NULL, NULL);
/* 创建管道 */
pipeline = gst_parse_launch("videotestsrc ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96", NULL);
/* 设置RTSP服务器的地址和端口 */
g_object_set(G_OBJECT(pay0), "server-port", 8554, NULL);
/* 启动管道 */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
/* ...(其他代码,如处理错误、清理等)... */
有了GStreamer管道的代码,你需要将其集成到你的Android应用中:
Activity
或Service
中调用JNI函数来初始化GStreamer并设置管道。appsrc
元素(如果适用)从Android摄像头捕获视频帧,并将其推送到GStreamer管道中。onPause
、onResume
、onDestroy
)中正确地停止和启动GStreamer。下面介绍的是大牛直播SDK的SmartRtspServer,不同于GStreamer,SmartRtspServer功能更完善,稳定性和商业度更高,实现逻辑如下:
Android内置轻量级RTSP服务模块接口设计 |
||
调用描述 |
接口 |
接口描述 |
SmartRTSPServerSDK |
||
初始化RTSP Server |
InitRtspServer |
Init rtsp server(和UnInitRtspServer配对使用,即便是启动多个RTSP服务,也只需调用一次InitRtspServer,请确保在OpenRtspServer之前调用) |
创建一个rtsp server |
OpenRtspServer |
创建一个rtsp server,返回rtsp server句柄 |
设置端口 |
SetRtspServerPort |
设置rtsp server 监听端口, 在StartRtspServer之前必须要设置端口 |
设置鉴权用户名、密码 |
SetRtspServerUserNamePassword |
设置rtsp server 鉴权用户名和密码, 这个可以不设置,只有需要鉴权的再设置 |
获取rtsp server当前会话数 |
GetRtspServerClientSessionNumbers |
获取rtsp server当前的客户会话数, 这个接口必须在StartRtspServer之后再调用 |
启动rtsp server |
StartRtspServer |
启动rtsp server |
停止rtsp server |
StopRtspServer |
停止rtsp server |
关闭rtsp server |
CloseRtspServer |
关闭rtsp server |
UnInit rtsp server |
UnInitRtspServer |
UnInit rtsp server(和InitRtspServer配对使用,即便是启动多个RTSP服务,也只需调用一次UnInitRtspServer) |
SmartRTSPServerSDK供Publisher调用的接口 |
||
设置rtsp的流名称 |
SetRtspStreamName |
设置rtsp的流名称 |
给要发布的rtsp流设置rtsp server |
AddRtspStreamServer |
给要发布的rtsp流设置rtsp server, 一个流可以发布到多个rtsp server上,rtsp server的创建启动请参考OpenRtspServer和StartRtspServer接口 |
清除设置的rtsp server |
ClearRtspStreamServer |
清除设置的rtsp server |
启动rtsp流 |
StartRtspStream |
启动rtsp流 |
停止rtsp流 |
StopRtspStream |
停止rtsp流 |
以SmartRtspServer采集摄像头为例,先初始化RTSP Server:
/*
* MainActivity.java
* Author: daniusdk.com
* WeChat:xinsheng120
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
context_ = this.getApplicationContext();
libPublisher = new SmartPublisherJniV2();
libPublisher.InitRtspServer(context_); //和UnInitRtspServer配对使用,即便是启动多个RTSP服务,也只需调用一次InitRtspServer,请确保在OpenRtspServer之前调用
}
启动、停止RTSP服务:
//启动/停止RTSP服务
class ButtonRtspServiceListener implements View.OnClickListener {
public void onClick(View v) {
if (isRTSPServiceRunning) {
stopRtspService();
btnRtspService.setText("启动RTSP服务");
btnRtspPublisher.setEnabled(false);
isRTSPServiceRunning = false;
return;
}
Log.i(TAG, "onClick start rtsp service..");
rtsp_handle_ = libPublisher.OpenRtspServer(0);
if (rtsp_handle_ == 0) {
Log.e(TAG, "创建rtsp server实例失败! 请检查SDK有效性");
} else {
int port = 8554;
if (libPublisher.SetRtspServerPort(rtsp_handle_, port) != 0) {
libPublisher.CloseRtspServer(rtsp_handle_);
rtsp_handle_ = 0;
Log.e(TAG, "创建rtsp server端口失败! 请检查端口是否重复或者端口不在范围内!");
}
if (libPublisher.StartRtspServer(rtsp_handle_, 0) == 0) {
Log.i(TAG, "启动rtsp server 成功!");
} else {
libPublisher.CloseRtspServer(rtsp_handle_);
rtsp_handle_ = 0;
Log.e(TAG, "启动rtsp server失败! 请检查设置的端口是否被占用!");
}
btnRtspService.setText("停止RTSP服务");
btnRtspPublisher.setEnabled(true);
isRTSPServiceRunning = true;
}
}
}
stopRtspService()实现如下:
//停止RTSP服务
private void stopRtspService() {
if(!isRTSPServiceRunning)
{
return;
}
if (libPublisher != null && rtsp_handle_ != 0) {
libPublisher.StopRtspServer(rtsp_handle_);
libPublisher.CloseRtspServer(rtsp_handle_);
rtsp_handle_ = 0;
}
}
发布、停止RTSP流:
//发布/停止RTSP流
class ButtonRtspPublisherListener implements View.OnClickListener {
public void onClick(View v) {
if (stream_publisher_.is_rtsp_publishing()) {
stopRtspPublisher();
btnRtspPublisher.setText("发布RTSP流");
btnGetRtspSessionNumbers.setEnabled(false);
btnRtspService.setEnabled(true);
return;
}
Log.i(TAG, "onClick start rtsp publisher..");
InitAndSetConfig();
String rtsp_stream_name = "stream1";
stream_publisher_.SetRtspStreamName(rtsp_stream_name);
stream_publisher_.ClearRtspStreamServer();
stream_publisher_.AddRtspStreamServer(rtsp_handle_);
if (!stream_publisher_.StartRtspStream()) {
stream_publisher_.try_release();
Log.e(TAG, "调用发布rtsp流接口失败!");
return;
}
startAudioRecorder();
startLayerPostThread();
btnRtspPublisher.setText("停止RTSP流");
btnGetRtspSessionNumbers.setEnabled(true);
btnRtspService.setEnabled(false);
}
}
stopRtspPublisher()实现如下:
//停止发布RTSP流
private void stopRtspPublisher() {
stream_publisher_.StopRtspStream();
stream_publisher_.try_release();
if (!stream_publisher_.is_publishing())
stopAudioRecorder();
}
Android平台实现内网环境轻量级RTSP服务,共享摄像头或麦克风数据,如果自身技术栈完备,可以考虑基于GStreamer实现,顺便也积累了流媒体相关的能力,如果商业化产品,对质量和功能性能要求非常高,可以用现成的SmartRtspServer,集成复杂度低,更稳定可靠,以上是二者的比较,感兴趣的开发者,可以单独跟我沟通探讨。