前言
最近一个项目需要用到rtsp拉流,总体对比下来,还是觉得live555比较轻量级,所以决定使用live555作为rtsp服务。
live555众所周知,只能以文件的形式拉流,不能实时的塞进去buf数据,不能实时的直播。
但是可以改。
就是为了改,决定研究一番。
想要学习源代码,就需要搭建一个开发环境,光靠看,不去操作就等于纸上谈兵肯定是不行的。
搭建一个研究源码和测试的环境,可以事半功倍;
一、PC环境介绍
我的PC机环境:
zhenghui@zh-pc:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.1 LTS Release: 22.04 Codename: jammy zhenghui@zh-pc:~$ zhenghui@zh-pc:~$ uname -a Linux zh-pc 5.15.0-52-generic #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux zhenghui@zh-pc:~$ zhenghui@zh-pc:~$ g++ --version g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. zhenghui@zh-pc:~$ zhenghui@zh-pc:~$ zhenghui@zh-pc:~$ gcc --version gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. zhenghui@zh-pc:~$
二、下载live555源码
http://www.live555.com/liveMedia/public/live555-latest.tar.gz
在linux下可以使用wget下载:
wget http://www.live555.com/liveMedia/public/live555-latest.tar.gz
解压:
tar -zxvf live555-latest.tar.gz cd live
三、清理一个舒服的学习环境
因为live555源码的作者给了很多配置文件,我们可以把不需要的直接删除,省的碍眼。
例如我的只剩下了这些目录和配置文件:
初次使用可以看到是没有Makefile文件的
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ ls mediaServer/ COPYING COPYING.LESSER DynamicRTSPServer.cpp DynamicRTSPServer.hh live555MediaServer.cpp Makefile.head Makefile.tail version.hh zhenghui@zh-pc:/data/project/live555_rtsp_server/live$
当然了直接执行make来编译也是不行的:
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ make -j20 make: *** 没有指明目标并且找不到 makefile。 停止。 zhenghui@zh-pc:/data/project/live555_rtsp_server/live$
执行genMakefiles来为每个目录生成Makefile
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ ./genMakefiles linux
可以看到现在就有了:
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ ls liveMedia/Makefile liveMedia/Makefile zhenghui@zh-pc:/data/project/live555_rtsp_server/live$
直接执行编译,会发现缺少ssl:
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ make -j20 cd liveMedia ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/liveMedia” c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 Media.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MediaSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 FramedSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 FramedFileSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 FramedFilter.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 ByteStreamFileSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 ByteStreamMultiFileSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 ByteStreamMemoryBufferSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 BasicUDPSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 DeviceSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 AudioInputDevice.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 WAVAudioFileSource.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEG1or2Demux.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEG1or2DemuxedElementaryStream.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEGVideoStreamFramer.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEG1or2VideoStreamFramer.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEG1or2VideoStreamDiscreteFramer.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEG4VideoStreamFramer.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 MPEG4VideoStreamDiscreteFramer.cpp c++ -c -Iinclude -I../UsageEnvironment/include -I../groupsock/include -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -DBSD=1 H264or5VideoStreamFramer.cpp In file included from include/RTPInterface.hh:30, from include/RTPSource.hh:28, from include/MultiFramedRTPSource.hh:26, from include/MPEG4LATMAudioRTPSource.hh:25, from MPEG4VideoStreamFramer.cpp:28: include/TLSState.hh:34:10: fatal error: openssl/ssl.h: 没有那个文件或目录 34 | #include <openssl/ssl.h> | ^~~~~~~~~~~~~~~ compilation terminated. make[1]: *** [Makefile:32:MPEG4VideoStreamFramer.o] 错误 1 make[1]: *** 正在等待未完成的任务.... MPEG1or2VideoStreamFramer.cpp: In member function ‘unsigned int MPEG1or2VideoStreamParser::parseSlice()’: MPEG1or2VideoStreamFramer.cpp:463:32: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 463 | << (void*)next4Bytes << "\n"; | ^~~~~~~~~~~~~~~~~ make[1]: 离开目录“/data/project/live555_rtsp_server/live/liveMedia” make: *** [Makefile:35:all] 错误 2 zhenghui@zh-pc:/data/project/live555_rtsp_server/live$
这个时候就需要编译openssl库了
编译方法也比较简单,此篇文字就不过多解读了,编译完成后,记录lib和include路径,我们需要修改一下配置文件,
例如config.linux:
需要在COMPILE_OPTS变量后面增加include路径,在LIBS_FOR_CONSOLE_APPLICATION后面增加lib路径即可。
COMPILE_OPTS = $(INCLUDES) -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 COMPILE_OPTS += -I/data/soft/build_librtmp/openssl-1.0.2j/_install/include C = c C_COMPILER = cc C_FLAGS = $(COMPILE_OPTS) $(CPPFLAGS) $(CFLAGS) CPP = cpp CPLUSPLUS_COMPILER = c++ CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1 $(CPPFLAGS) $(CXXFLAGS) OBJ = o LINK = c++ -o LINK_OPTS = -L. $(LDFLAGS) CONSOLE_LINK_OPTS = $(LINK_OPTS) LIBRARY_LINK = ar cr LIBRARY_LINK_OPTS = LIB_SUFFIX = a LIBS_FOR_CONSOLE_APPLICATION = -lssl -lcrypto LIBS_FOR_CONSOLE_APPLICATION += -L/data/soft/build_librtmp/openssl-1.0.2j/_install/lib LIBS_FOR_GUI_APPLICATION = EXE =
然后重新生成makefile
./genMakefiles linux
重新编译:
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ make -j20 。。。 。。。 。。 。。 。 。。 。 。 。 。 。。。。 。。。。 zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ make -j20 cd liveMedia ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/liveMedia” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/liveMedia” cd groupsock ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/groupsock” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/groupsock” cd UsageEnvironment ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/UsageEnvironment” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/UsageEnvironment” cd BasicUsageEnvironment ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/BasicUsageEnvironment” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/BasicUsageEnvironment” cd testProgs ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/testProgs” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/testProgs” cd mediaServer ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/mediaServer” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/mediaServer” cd proxyServer ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/proxyServer” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/proxyServer” cd hlsProxy ; make make[1]: 进入目录“/data/project/live555_rtsp_server/live/hlsProxy” make[1]: 对“all”无需做任何事。 make[1]: 离开目录“/data/project/live555_rtsp_server/live/hlsProxy” For more information about this source code (including your obligations under the LGPL), please see our FAQ at http://live555.com/liveMedia/faq.html zhenghui@zh-pc:/data/project/live555_rtsp_server/live$
四、测试
可以运行一下./mediaServer/live555MediaServer
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ ./mediaServer/live555MediaServer LIVE555 Media Server version 1.10 (LIVE555 Streaming Media library version 2022.10.01). Play streams from this server using the URL rtsp://192.168.144.109:8554/<filename> where <filename> is a file present in the current directory. Each file's type is inferred from its name suffix: ".264" => a H.264 Video Elementary Stream file ".265" => a H.265 Video Elementary Stream file ".aac" => an AAC Audio (ADTS format) file ".ac3" => an AC-3 Audio file ".amr" => an AMR Audio file ".dv" => a DV Video file ".m4e" => a MPEG-4 Video Elementary Stream file ".mkv" => a Matroska audio+video+(optional)subtitles file ".mp3" => a MPEG-1 or 2 Audio file ".mpg" => a MPEG-1 or 2 Program Stream (audio+video) file ".ogg" or ".ogv" or ".opus" => an Ogg audio and/or video file ".ts" => a MPEG Transport Stream file (a ".tsx" index file - if present - provides server 'trick play' support) ".vob" => a VOB (MPEG-2 video with AC-3 audio) file ".wav" => a WAV Audio file ".webm" => a WebM audio(Vorbis)+video(VP8) file See http://www.live555.com/mediaServer/ for additional documentation. (We use port 8000 for optional RTSP-over-HTTP tunneling).)
给我们提示了可以使用“rtsp://192.168.144.109:8554/文件名”的形式来访问rtsp流;
还说明了支持的媒体文件后缀名。
而且文件需要放到当前运行程序的目录下。
我放了一个264文件,文件名是1080P.264:
zhenghui@zh-pc:/data/project/live555_rtsp_server/live$ ls 1080P.264 1080P.264 zhenghui@zh-pc:/data/project/live555_rtsp_server/live$
那么拉流地址就是:rtsp://192.168.144.109:8554/1080P.264