live555是什么就不介绍了,你点进来肯定知道是什么东西了,前段时间折腾了一下rtsp相关的东西,觉得有必要记录一下。
废话不多说,首先下载live555
最新的live555源码下载
在Android Studio3里新建一个工程,记得勾选C++支持
将下载的live555源码解压出来后,放到src/main/cpp的目录下,有的是src/main/jni目录
默认的AS工程是使用CMAKE编译,没学过的可以看下这篇文章CMake 入门实战
然后直接编辑工程根目录的CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_definitions(-DSOCKLEN_T=socklen_t)
add_definitions(-DNO_SSTREAM=1)
add_definitions(-DNEWLOCALE_NOT_USED)
#add_definitions(-D_LARGEFILE_SOURCE=1)
#add_definitions(-D_FILE_OFFSET_BITS=64)
add_definitions(-DBSD=1)
include_directories(src/main/cpp/live/UsageEnvironment/include)
include_directories(src/main/cpp/live/BasicUsageEnvironment/include)
include_directories(src/main/cpp/live/groupsock/include)
include_directories(src/main/cpp/live/liveMedia/include)
file(GLOB BasicUsageEnvironmentFiles
src/main/cpp/live/BasicUsageEnvironment/*.cpp)
add_library(BasicUsageEnvironment
${BasicUsageEnvironmentFiles})
file(GLOB groupsockfiles
src/main/cpp/live/groupsock/*.cpp src/main/cpp/live/groupsock/*.c)
add_library(groupsock ${groupsockfiles})
file(GLOB liveMediaFiles
src/main/cpp/live/liveMedia/*.hh src/main/cpp/live/liveMedia/*.cpp src/main/cpp/live/liveMedia/*.c)
add_library(liveMedia ${liveMediaFiles})
file(GLOB UsageEnvironmentFiles
src/main/cpp/live/UsageEnvironment/*.cpp)
add_library(UsageEnvironment ${UsageEnvironmentFiles})
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp )
find_library(log-lib
log )
target_link_libraries( native-lib
${log-lib}
liveMedia
groupsock
BasicUsageEnvironment
UsageEnvironment )
其中的一些编译标志,可以参考下载的live555源码里的config.armlinux
CROSS_COMPILE?= arm-elf-
COMPILE_OPTS = $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
C = c
C_COMPILER = $(CROSS_COMPILE)gcc
C_FLAGS = $(COMPILE_OPTS)
CPP = cpp
CPLUSPLUS_COMPILER = $(CROSS_COMPILE)g++
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1
OBJ = o
LINK = $(CROSS_COMPILE)g++ -o
LINK_OPTS =
CONSOLE_LINK_OPTS = $(LINK_OPTS)
LIBRARY_LINK = $(CROSS_COMPILE)ar cr
LIBRARY_LINK_OPTS = $(LINK_OPTS)
LIB_SUFFIX = a
LIBS_FOR_CONSOLE_APPLICATION =
LIBS_FOR_GUI_APPLICATION =
EXE =
这里有好几个flag,但是添加了 -D_LARGEFILE_SOURCE=1和-D_FILE_OFFSET_BITS=64之后就在Win10上用ndk16就编译不过了,不知道什么原因,直接屏蔽了,好像也没什么影响
然后在build.gradle里设置只编译armeabi-v7a,因为编译其他64位的会编译出错,暂时只用到armeabi-v7a,所以只编译一个就行了。以后有需要再看看什么问题,谁解决了在评论里教我一下
android {
...
defaultConfig {
...
ndk {
abiFilters 'armeabi-v7a'
}
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
然后在AS里点击编译按钮,正常的话就直接编出libnative-lib.so了
接下来就是使用live555了,先在MainActivity.java里定义一个public native String start(String fileName);
本地方法,用来启动Rtsp服务器,这里传入一个H264的码流文件,客户端就可以通过rtsp的url来点播视频了
在native-lib.cpp实现我们的start方法,代码可以参看live555里面的样例,注意这里代码会一直阻塞,直到Rtspserver退出才会退出这个方法
可以参考Live555在Android下改造
extern "C" JNIEXPORT jstring JNICALL Java_com_example_live555_MainActivity_start(JNIEnv *env, jobject instance, jstring fileName_) {
const char *inputFilename = env->GetStringUTFChars(fileName_, 0);
FILE *file = fopen(inputFilename, "rb");
if (!file) {
LOGE("couldn't open %s", inputFilename);
exit(1);
}
fclose(file);
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env_ = BasicUsageEnvironment::createNew(*scheduler);
UserAuthenticationDatabase* authDB = NULL;
// Create the RTSP server:
RTSPServer* rtspServer = RTSPServer::createNew(*env_, 8554, authDB);
if (rtspServer == NULL) {
LOGE("Failed to create RTSP server: %s", env_->getResultMsg());
exit(1);
}
char const* descriptionString = "Session streamed by \"testOnDemandRTSPServer\"";
char const* streamName = "v";
ServerMediaSession* sms = ServerMediaSession::createNew(*env_, streamName, streamName, descriptionString);
sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(*env_, inputFilename, True));
rtspServer->addServerMediaSession(sms);
char* url = rtspServer->rtspURL(sms);
LOGE("%s stream, from the file %s ",streamName, inputFilename);
LOGE("Play this stream using the URL: %s", url);
delete[] url;
env->ReleaseStringUTFChars(fileName_, inputFilename);
env_->taskScheduler().doEventLoop(); // does not return
}
到这里就可以开启rtsp服务器了,在MainActivity里启动一个线程,在线程里调用start方法,传入H264码流的文件路径就可以了,注意打开读写外部存储的权限
本文示例源码下载