我们的目标是从一个USB摄像头和麦克风生成H264 + AAC直播流。
为了达到这个目标,我们使用了以下链:USB摄像机->ffmpeg->RSTP直播555。
最后,当我们与一个客户机连接时,live stream可以工作,VLC或ffplay,我们可以看到摄像机拍摄。
我们唯一的问题是因为我们只能有一个有限的连接数(客户端vlc)和数字与源的分辨率有关。
如果超过这个数字,所有VLC客户机都开始显示人工产品。
源的分辨率320 x 240只允许6个VLC连接。
源的分辨率640x480只允许3个VLC连接。
源的分辨率1920x1080只允许1个VLC连接。
我们已经检查了cpu使用率和带宽,cpu使用率是大约40%,平均带宽为1Mbit。
1) 我们使用ffmpeg从相机中捕获图像并进行转换至H264+AAC帧(AVC编码)
2) 这些帧被推到一个循环队列中
3) 在一个线程中,我们创建了一个RTP服务器、媒体会话和两个子会话,一个用于视频,另一个用于音频(参见代码
4) 从DeviceSource.cpp开始,我们创建了一个读取循环队列中的帧。
5) 当客户端连接到RTPserver时,我们创建一个NewStreamSource
还有一个新的想法。从下面的代码中可以看到,对于视频流源,我们为我们留下的音频。
参考代码
//**********************************************************************************
unsigned long WINAPI Live555Thread (void *param)
{
OutPacketBuffer::maxSize = MAX_FRAME_SIZE;
TaskScheduler *serverTsk = BasicTaskScheduler::createNew();
UsageEnvironment *serverEnv =
BasicUsageEnvironment::createNew(*serverTsk);
RTSPServer *rtspServer = RTSPServer::createNew(*serverEnv,
g_nRTSPServerPort, NULL);
ServerMediaSession *sms;
if (rtspServer == NULL) {
*serverEnv << "LIVE555: Failed to create RTSP server: %s\n",
serverEnv->getResultMsg();
return 0;
}
else {
char const* descriptionString = "Session streamed by
\"QMServer\"";
char RTSP_Address[1024];
RTSP_Address[0]=0x00;
sms = ServerMediaSession::createNew(*serverEnv,
RTSP_Address, RTSP_Address, descriptionString);
sms->addSubsession(Live555ServerMediaSubsession::createNew(VIDEO_TYPE,*serverEnv, ESTIMATED_VIDEO_BITRATE));
sms->addSubsession(Live555ServerMediaSubsession::createNew(AUDIO_TYPE,*serverEnv, ESTIMATED_AUDIO_BITRATE));
rtspServer->addServerMediaSession(sms);
}
char* url = rtspServer->rtspURL(sms);
*serverEnv << "Play this stream using the URL \"" << url <<
"\"\n";
for (;;) {
serverEnv->taskScheduler().doEventLoop(&g_cExitThread); //
does not return
if (g_cExitThread)
break;
}
Medium::close(rtspServer);
return 0;
}
//**********************************************************************************
FramedSource* Live555ServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate)
{
estBitrate = fEstimatedKbps;
m_source = Live555Source::createNew(envir(), m_type, false);
if (m_type == VIDEO_TYPE) {
return (H264VideoStreamDiscreteFramer::createNew(envir(),
m_source));
}
else
return m_source;
}
RTPSink* Live555ServerMediaSubsession::createNewRTPSink (Groupsock*rtpGroupsock, unsigned char /*rtpPayloadTypeIfDynamic*/, FramedSource* inputSource)
{
OutPacketBuffer::maxSize = MAX_FRAME_SIZE;
if (m_type == VIDEO_TYPE) {
return (H264VideoRTPSink::createNew(envir(), rtpGroupsock,
96));
}
else {
unsigned char audioSpecificConfig[2];
char fConfigStr[10];
audioSpecificConfig[0] = (AUDIO_AAC_TYPE << 3) |
(AUDIO_SRATE_INDEX >> 1);
audioSpecificConfig[1] = (AUDIO_SRATE_INDEX << 7) |
(AUDIO_CHANNELS << 3);
sprintf(fConfigStr, "%02X%02x", audioSpecificConfig[0],
audioSpecificConfig[1]);
return (MPEG4GenericRTPSink::createNew(envir(),
rtpGroupsock, 96, AUDIO_SRATE, "audio", "AAC-hbr", fConfigStr,
AUDIO_CHANNELS));
}
}
//________________________________________________________________
原文 https://live-devel.live555.narkive.com/9zGF7lPK/rstp-live-streaming-from-usb-camera