live555是使用十分广泛的开源流媒体服务器,之前也看过其他人写的live555的学习笔记,在这里自己简单总结下。

live555源代码有以下几个明显的特点:

1.头文件是.hh后缀的,但没觉得和.h后缀的有什么不同

2.采用了面向对象的程序设计思路,里面各种对象

好了,不罗嗦,使用vc2010打开live555的vc工程,看到live555源代码结构如下:

源代码由5个工程构成(4个库和一个主程序):

libUsageEnvironment.lib;libliveMedia.lib;libgroupsock.lib;libBasicUsageEnvironment.lib;以及live555MediaServer

这里我们只分析live555MediaServer这个主程序,其实代码量并不大,主要有两个CPP:DynamicRTSPServer.cpp和live555MediaServer.cpp

程序的main()在live555MediaServer.cpp中,在main()中调用了DynamicRTSPServer中的类

不废话,直接贴上有注释的源码

live555MediaServer.cpp:

#include <BasicUsageEnvironment.hh>
#include "DynamicRTSPServer.hh"
#include "version.hh"int main(int argc, char** argv) {// Begin by setting up our usage environment:// TaskScheduler用于任务计划TaskScheduler* scheduler = BasicTaskScheduler::createNew();// UsageEnvironment用于输出UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);UserAuthenticationDatabase* authDB = NULL;
#ifdef ACCESS_CONTROL// To implement client access control to the RTSP server, do the following:authDB = new UserAuthenticationDatabase;authDB->addUserRecord("username1", "password1"); // replace these with real strings// Repeat the above with each <username>, <password> that you wish to allow// access to the server.
#endif//建立 RTSP server.  使用默认端口 (554),// and then with the alternative port number (8554):RTSPServer* rtspServer;portNumBits rtspServerPortNum = 554;//创建 RTSPServer实例rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);if (rtspServer == NULL) {rtspServerPortNum = 8554;rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);}if (rtspServer == NULL) {*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";exit(1);}//用到了运算符重载*env << "LIVE555 Media Server\n";*env << "\tversion " << MEDIA_SERVER_VERSION_STRING<< " (LIVE555 Streaming Media library version "<< LIVEMEDIA_LIBRARY_VERSION_STRING << ").\n";char* urlPrefix = rtspServer->rtspURLPrefix();*env << "Play streams from this server using the URL\n\t"<< urlPrefix << "<filename>\nwhere <filename> is a file present in the current directory.\n";*env << "Each file's type is inferred from its name suffix:\n";*env << "\t\".aac\" => an AAC Audio (ADTS format) file\n";*env << "\t\".amr\" => an AMR Audio file\n";*env << "\t\".m4e\" => a MPEG-4 Video Elementary Stream file\n";*env << "\t\".dv\" => a DV Video file\n";*env << "\t\".mp3\" => a MPEG-1 or 2 Audio file\n";*env << "\t\".mpg\" => a MPEG-1 or 2 Program Stream (audio+video) file\n";*env << "\t\".ts\" => a MPEG Transport Stream file\n";*env << "\t\t(a \".tsx\" index file - if present - provides server 'trick play' support)\n";*env << "\t\".wav\" => a WAV Audio file\n";*env << "See http://www.live555.com/mediaServer/ for additional documentation.\n";// Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.// Try first with the default HTTP port (80), and then with the alternative HTTP// port numbers (8000 and 8080).if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {*env << "(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";} else {*env << "(RTSP-over-HTTP tunneling is not available.)\n";}//进入一个永久的循环env->taskScheduler().doEventLoop(); // does not returnreturn 0; // only to prevent compiler warning
}

DynamicRTSPServer.cpp:

#include "DynamicRTSPServer.hh"
#include <liveMedia.hh>
#include <string.h>DynamicRTSPServer*
DynamicRTSPServer::createNew(UsageEnvironment& env, Port ourPort,UserAuthenticationDatabase* authDatabase,unsigned reclamationTestSeconds) {int ourSocket = -1;do {//建立TCP socket(socket(),bind(),listen()...)int ourSocket = setUpOurSocket(env, ourPort);if (ourSocket == -1) break;return new DynamicRTSPServer(env, ourSocket, ourPort, authDatabase, reclamationTestSeconds);} while (0);if (ourSocket != -1) ::closeSocket(ourSocket);return NULL;
}DynamicRTSPServer::DynamicRTSPServer(UsageEnvironment& env, int ourSocket,Port ourPort,UserAuthenticationDatabase* authDatabase, unsigned reclamationTestSeconds): RTSPServer(env, ourSocket, ourPort, authDatabase, reclamationTestSeconds) {
}DynamicRTSPServer::~DynamicRTSPServer() {
}static ServerMediaSession* createNewSMS(UsageEnvironment& env,char const* fileName, FILE* fid); // forward//查找ServerMediaSession(对应服务器上一个媒体文件,,或设备),如果没有的话就创建一个
//streamName例:A.avi
ServerMediaSession*
DynamicRTSPServer::lookupServerMediaSession(char const* streamName) {// First, check whether the specified "streamName" exists as a local file:FILE* fid = fopen(streamName, "rb");//如果返回文件指针不为空,则文件存在Boolean fileExists = fid != NULL;// Next, check whether we already have a "ServerMediaSession" for this file://看看是否有这个ServerMediaSessionServerMediaSession* sms = RTSPServer::lookupServerMediaSession(streamName);Boolean smsExists = sms != NULL;// Handle the four possibilities for "fileExists" and "smsExists"://文件没了,ServerMediaSession有,删之if (!fileExists) {if (smsExists) {// "sms" was created for a file that no longer exists. Remove it:removeServerMediaSession(sms);}return NULL;} else {//文件有,ServerMediaSession无,加之if (!smsExists) {// Create a new "ServerMediaSession" object for streaming from the named file.sms = createNewSMS(envir(), streamName, fid);addServerMediaSession(sms);}fclose(fid);return sms;}
}#define NEW_SMS(description) do {\
char const* descStr = description\", streamed by the LIVE555 Media Server";\
sms = ServerMediaSession::createNew(env, fileName, fileName, descStr);\
} while(0)//创建一个ServerMediaSession
static ServerMediaSession* createNewSMS(UsageEnvironment& env,char const* fileName, FILE* /*fid*/) {// Use the file name extension to determine the type of "ServerMediaSession"://获取扩展名,以“.”开始。不严密,万一文件名有多个点?char const* extension = strrchr(fileName, '.');if (extension == NULL) return NULL;ServerMediaSession* sms = NULL;Boolean const reuseSource = False;if (strcmp(extension, ".aac") == 0) {// Assumed to be an AAC Audio (ADTS format) file:// 调用ServerMediaSession::createNew()//还会调用MediaSubsessionNEW_SMS("AAC Audio");sms->addSubsession(ADTSAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));} else if (strcmp(extension, ".amr") == 0) {// Assumed to be an AMR Audio file:NEW_SMS("AMR Audio");sms->addSubsession(AMRAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));} else if (strcmp(extension, ".m4e") == 0) {// Assumed to be a MPEG-4 Video Elementary Stream file:NEW_SMS("MPEG-4 Video");sms->addSubsession(MPEG4VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));} else if (strcmp(extension, ".mp3") == 0) {// Assumed to be a MPEG-1 or 2 Audio file:NEW_SMS("MPEG-1 or 2 Audio");// To stream using 'ADUs' rather than raw MP3 frames, uncomment the following:
//#define STREAM_USING_ADUS 1// To also reorder ADUs before streaming, uncomment the following:
//#define INTERLEAVE_ADUS 1// (For more information about ADUs and interleaving,//  see <http://www.live555.com/rtp-mp3/>)Boolean useADUs = False;Interleaving* interleaving = NULL;
#ifdef STREAM_USING_ADUSuseADUs = True;
#ifdef INTERLEAVE_ADUSunsigned char interleaveCycle[] = {0,2,1,3}; // or choose your own...unsigned const interleaveCycleSize= (sizeof interleaveCycle)/(sizeof (unsigned char));interleaving = new Interleaving(interleaveCycleSize, interleaveCycle);
#endif
#endifsms->addSubsession(MP3AudioFileServerMediaSubsession::createNew(env, fileName, reuseSource, useADUs, interleaving));} else if (strcmp(extension, ".mpg") == 0) {// Assumed to be a MPEG-1 or 2 Program Stream (audio+video) file:NEW_SMS("MPEG-1 or 2 Program Stream");MPEG1or2FileServerDemux* demux= MPEG1or2FileServerDemux::createNew(env, fileName, reuseSource);sms->addSubsession(demux->newVideoServerMediaSubsession());sms->addSubsession(demux->newAudioServerMediaSubsession());} else if (strcmp(extension, ".ts") == 0) {// Assumed to be a MPEG Transport Stream file:// Use an index file name that's the same as the TS file name, except with ".tsx":unsigned indexFileNameLen = strlen(fileName) + 2; // allow for trailing "x\0"char* indexFileName = new char[indexFileNameLen];sprintf(indexFileName, "%sx", fileName);NEW_SMS("MPEG Transport Stream");sms->addSubsession(MPEG2TransportFileServerMediaSubsession::createNew(env, fileName, indexFileName, reuseSource));delete[] indexFileName;} else if (strcmp(extension, ".wav") == 0) {// Assumed to be a WAV Audio file:NEW_SMS("WAV Audio Stream");// To convert 16-bit PCM data to 8-bit u-law, prior to streaming,// change the following to True:Boolean convertToULaw = False;sms->addSubsession(WAVAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource, convertToULaw));} else if (strcmp(extension, ".dv") == 0) {// Assumed to be a DV Video file// First, make sure that the RTPSinks' buffers will be large enough to handle the huge size of DV frames (as big as 288000).OutPacketBuffer::maxSize = 300000;NEW_SMS("DV Video");sms->addSubsession(DVVideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));}return sms;
}

live555源代码(VC6):http://download.csdn.net/detail/leixiaohua1020/6374387

live555 源代码简单分析1:主程序相关推荐

  1. ffmpeg 源代码简单分析 : avcodec_decode_video2()

    2019独角兽企业重金招聘Python工程师标准>>> 此前写了好几篇ffmpeg源代码分析文章,列表如下: 图解FFMPEG打开媒体的函数avformat_open_input f ...

  2. H.264官方软件JM源代码简单分析-解码器ldecod

    ===================================================== H.264/H.265 官方源代码分析文章: H.264官方软件JM源代码简单分析-编码器l ...

  3. FFmpeg与libx264接口源代码简单分析

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  4. x264源代码简单分析:熵编码(Entropy Encoding)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  5. x264源代码简单分析:宏块编码(Encode)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  6. x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  7. x264源代码简单分析:滤波(Filter)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  8. x264源代码简单分析:x264_slice_write()

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  9. x264源代码简单分析:编码器主干部分-2

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

最新文章

  1. 百度二面:一个线程OOM了,其它线程还能运行吗?
  2. Golang向Templates 插入对象的值
  3. EasyNet.Solr架构
  4. cascader 动态加载 回显_Element中的Cascader(级联列表)动态加载省\市\区数据的方法...
  5. Spark On YARN 集群安装部署
  6. Linux调度系统全景指南(终结篇)
  7. Head First C学习日志 第七章 创建可变参数的函数
  8. 数据 格式化 format
  9. html给span标签设置index,html – 绝对定位嵌套元素的z-index
  10. ​实战:Flink 1.12 维表 Join Hive 最新分区功能体验
  11. java 获取方法名
  12. Android SurfaceView双缓存
  13. [NLP] 中文文本相似度实战
  14. 公开说说别人看不到_为什么我在QQ空间里面发表说说别人看不到?
  15. Jenkins Pipeline 手记(1)—— 什么是CPS编程
  16. git 如何下载单个文件夹或者单个文件
  17. 想要成为一名合格的数据分析师,需要学习哪些类型的书
  18. matlab shading 的用法说明
  19. 动作捕捉技术对演员的演技诉求
  20. Week15—字典树应用,字符串包含问题

热门文章

  1. 流程管理系统成功实施的六个步骤
  2. [导入]Nutch 简介 [官方]
  3. Bailian2759 神奇的口袋(2)【DP】
  4. 中英文对照 —— 航空航天航海、交通运输工具
  5. 图与图算法在实际中的应用
  6. Python 求解斐波那切(三种方法)
  7. C 标准库——cmath/math.h
  8. 重访 list comprehension
  9. 条件编译宏定义_C语言学习- 预处理指令2 - 条件编译
  10. python装饰器详解-这是我见过最全面的Python装饰器详解!没有学不会这种说法!...