一:下载live555
第一种方式:下载官方源码Index of /liveMedia/public
第二种方式:下载我适配好的live555(解决编译报错,同时推流pcm和h264,解决第二次拉流无音频的bug)live555rtsp推流h264和pcm资源-CSDN文库
二:编译安装live555(官方源码)
1:进入源码目录,新增config.mc6670,内容如下:
CROSS_COMPILE?= aarch64-linux-gnu-
COMPILE_OPTS = $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DNO_OPENSSL=1 -DNO_STD_LIB
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 =
PREFIX = /home/hfzuo/work/live555/_install
2:适配C++库版本:如果嵌入式系统的C++库版本低于C++20,您需要在config.mc6670文件的COMPILE_OPTS项中追加-DNO_STD_LIB。以避免因版本不兼容导致的语法报错。
3:处理openssl库依赖:如果嵌入式系统中没有安装openssl库,您需要在config.mc6670文件的COMPILE_OPTS项中追加-DNO_OPENSSL=1。这样做可以防止因缺少openssl库而导致的编译错误。
4:运行genMakefiles生成makefile,根据后缀名匹配对应的config文件。
./genMakefiles mc6670
5:修改源码
5.1:设置pcm和h264推流到同一个地 址/home/hfzuo/work/live555/live/testProgs/testOnDemandRTSPServer.cpp
// A H.264 video elementary stream:
{
OutPacketBuffer::maxSize = 1000000;//防止单帧数据过大
char const* streamName = "h264ESVideoTest";
char const* inputFileName = "/usr/local/app/datatest.264";
char const* inputFileName1 = "/tmp/pcm.wav";
//char const* inputFileName1 = "/tmp/pcm.aac";
ServerMediaSession* sms
= ServerMediaSession::createNew(*env, streamName, streamName,
descriptionString);
sms->addSubsession(H264VideoFileServerMediaSubsession
::createNew(*env, inputFileName, reuseFirstSource));
Boolean convertToULaw = 1;
sms->addSubsession(WAVAudioFileServerMediaSubsession
::createNew(*env, inputFileName1, reuseFirstSource, convertToULaw));
// sms->addSubsession(ADTSAudioFileServerMediaSubsession
// ::createNew(*env, inputFileName1, reuseFirstSource));
rtspServer->addServerMediaSession(sms);
announceStream(rtspServer, sms, streamName, inputFileName);
}
5.2:固定wav头数据,因为我们实际传输是pcm裸流,并没有wav头信息,所以需要手动填写相关音频格式,如果内存里的音频数据存在变化的,可以以传参的方式固定,下面是48K 16BIT 2CH的代码修改
WAVAudioFileSource::WAVAudioFileSource(UsageEnvironment& env, FILE* fid)
: AudioInputDevice(env, 0, 0, 0, 0)/* set the real parameters later */,
fFid(fid), fFidIsSeekable(False), fLastPlayTime(0), fHaveStartedReading(False), fWAVHeaderSize(0), fFileSize(0),
fScaleFactor(1), fLimitNumBytesToStream(False), fNumBytesToStream(0), fAudioFormat(WA_UNKNOWN) {
Boolean success = False; // until we learn otherwise
do {
printf("hfzuo wav head\r\n");//hfzuodebug
fAudioFormat = 1;
printf("fAudioFormat=%d\r\n",fAudioFormat);//hfzuodebug
if (fAudioFormat != WA_PCM && fAudioFormat != WA_PCMA && fAudioFormat != WA_PCMU && fAudioFormat != WA_IMA_ADPCM) {
// It's a format that we don't (yet) understand
env.setResultMsg("Audio format is not one that we handle (PCM/PCMU/PCMA or IMA ADPCM)");
break;
}
fNumChannels = 2;
printf("fNumChannels=%d\r\n",fNumChannels);//hfzuodebug
if (fNumChannels < 1 || fNumChannels > 2) { // invalid # channels
char errMsg[100];
sprintf(errMsg, "Bad # channels: %d", fNumChannels);
env.setResultMsg(errMsg);
break;
}
fSamplingFrequency=48000;
printf("fSamplingFrequency=%d\r\n",fSamplingFrequency);//hfzuodebug
if (fSamplingFrequency == 0) {
env.setResultMsg("Bad sampling frequency: 0");
break;
}
fBitsPerSample = 16;
printf("fBitsPerSample=%d\r\n",fBitsPerSample);//hfzuodebug
if (fBitsPerSample == 0) {
env.setResultMsg("Bad bits-per-sample: 0");
break;
}
fWAVHeaderSize = 4294967295;//(unsigned)TellFile64(fid);
printf("fWAVHeaderSize=%u\r\n",fWAVHeaderSize);//hfzuodebug
success = True;
} while (0);
if (!success) {
env.setResultMsg("Bad WAV file format");
// Set "fBitsPerSample" to zero, to indicate failure:
fBitsPerSample = 0;
return;
}
fPlayTimePerSample = 1e6/(double)fSamplingFrequency;
printf("fPlayTimePerSample=%d\r\n",fPlayTimePerSample);//hfzuodebug
unsigned maxSamplesPerFrame = (1400*8)/(fNumChannels*fBitsPerSample);
unsigned desiredSamplesPerFrame = (unsigned)(0.02*fSamplingFrequency);
unsigned samplesPerFrame = desiredSamplesPerFrame < maxSamplesPerFrame ? desiredSamplesPerFrame : maxSamplesPerFrame;
fPreferredFrameSize = (samplesPerFrame*fNumChannels*fBitsPerSample)/8;
printf("maxSamplesPerFrame=%d\r\n",maxSamplesPerFrame);//hfzuodebug
printf("desiredSamplesPerFrame=%d\r\n",desiredSamplesPerFrame);//hfzuodebug
printf("samplesPerFrame=%d\r\n",samplesPerFrame);//hfzuodebug
printf("fPreferredFrameSize=%d\r\n",fPreferredFrameSize);//hfzuodebug
fFidIsSeekable = FileIsSeekable(fFid);
printf("fFidIsSeekable=%d\r\n",fFidIsSeekable);//hfzuodebug
#ifndef READ_FROM_FILES_SYNCHRONOUSLY
printf("synchronously\r\n");//hfzuodebug
makeSocketNonBlocking(fileno(fFid));
#endif
}
6:解决MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size (300552). 25411 bytes of trailing data was dropped!
Correct this by increasing "OutPacketBuffer::maxSize" to at least 325411, *before* creating this 'RTPSink'. (Current value is 300000.)报错
解决办法:
a:live/liveMedia/MultiFramedRTPSource.cpp :increaseReceiveBufferTo(env, RTPgs-> socketNUm(), 2000000)
b:live/liveMedia/StreamParser.cpp:#define BANK_SIZE 1200000//150000
c: live/liveMedia/MediaSink.cpp : unsigned OutPacketBuffer::maxSize = 600000;
d:mediaServer/DynamicRTSPServer.cpp:OutPacketBuffer::maxSize = 600000;
e:testH264VideoStreamer.cpp : OutPacketBuffer::maxSize = 600000;
f:testProgs/playCommon.cpp: unsigned fileSinkBufferSize = 600000;
7:编译安装
make make install PREFIX=/home/hfzuo/work/live555/_install
将 testOnDemandRTSPServer 拷贝到开发板运行即可及
三:开发板从内存获取pcm和h264通过fifo发送给live555
get_h264_frame:获取h264接口
get_pcm_frame:获取pcm接口
h264:
mkfifo("/usr/local/app/datatest.264", 0666);
int fd = open("/usr/local/app/datatest.264", O_WRONLY);
for(;;)
{
uint8_t buff[1024*1024*8]
int size=get_h264_frame(buff);
write(fd, (buff),size);
}
pcm:
mkfifo("/tmp/pcm.wav", 0666);
int fd = open("/tmp/pcm.wav", O_WRONLY);
for(;;)
{
uint8_t buff[2048]
int size=get_pcm_frame(buff);
write(fd, (buff),size);
}
四:VLC拉流
拉流地址:rtsp://192.168.1.218:8554/h264ESVideoTest,打开播放器如VLC输入拉流地址即可得到视音频
实际测试效果:延迟大概1-2秒,不存在视音频不同步的问题,只要视音频数据写入fifo及时(按音频采样率和视频帧率)live会自动给视音频流打上时间戳。如果出现视音频不同步问题,一定会是视音频写入fifo时存在延迟情况