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 return return 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:
//看看是否有这个ServerMediaSession
ServerMediaSession* 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()
//还会调用MediaSubsession
NEW_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_ADUS
useADUs = True;
#ifdef INTERLEAVE_ADUS
unsigned char interleaveCycle[] = {0,2,1,3}; // or choose your own...
unsigned const interleaveCycleSize
= (sizeof interleaveCycle)/(sizeof (unsigned char));
interleaving = new Interleaving(interleaveCycleSize, interleaveCycle);
#endif
#endif
sms->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 源代码简单分析1:主程序的更多相关文章

  1. Ffmpeg解析media容器过程/ ffmpeg 源代码简单分析 : av_read_frame()

    ffmpeg 源代码简单分析 : av_read_frame() http://blog.csdn.net/leixiaohua1020/article/details/12678577 ffmpeg ...

  2. FFmpeg的HEVC解码器源代码简单分析:环路滤波(Loop Filter)

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  3. FFmpeg的HEVC解码器源代码简单分析:CTU解码(CTU Decode)部分-TU

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  4. FFmpeg的HEVC解码器源代码简单分析:CTU解码(CTU Decode)部分-PU

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  5. FFmpeg的HEVC解码器源代码简单分析:解码器主干部分

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  6. FFmpeg的HEVC解码器源代码简单分析:解析器(Parser)部分

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  7. FFmpeg的HEVC解码器源代码简单分析:概述

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

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

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

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

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

随机推荐

  1. springmvc-时间类型转换器

    springmvc 没有默认实现时间类型的转化,需要如下代码实现此功能. @InitBinder public void initBinder(HttpServletRequest request,S ...

  2. 禁用UITableViewCell 重用机制

    有时候不想让Cell重用,怎么办勒.接下来介绍两种方法 方法一 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAt ...

  3. Bin & Jing in wonderland(概率,组合数学)

    Problem 2103 Bin & Jing in wonderland Accept: 201    Submit: 1048 Time Limit: 1000 mSec    Memor ...

  4. Android窗口管理服务WindowManagerService显示窗口动画的原理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8611754 在前一文中,我们分析了Activi ...

  5. 为github帐号添加SSH keys

    为github帐号添加SSH keys 2012-05-26 00:05 34279人阅读 评论(6) 收藏 举报 ssh文本编辑gitvim工具up 使用git clone命令从github上同步g ...

  6. [Spring入门学习笔记][maven]

    什么是maven? 我的理解: 一个项目有一大堆依赖包的时候,没必要下下来,可以利用maven中的pom.xml 指定需要那些依赖包,让maven去本地中央库(如果没找到)->网上仓库库帮你调用 ...

  7. Android-------手机屏幕适配之文件适配

    public class Main {         //定义文件本地存储路径,可按照需求更改         private final static String rootPath = &quo ...

  8. Win7刷新环境变量

    在“我的电脑”->“属性”->“高级”->“环境变量”中增加或修改环境变量后,需重启系统才能使之生效.有没有什么方法可让它即时生效呢? 下面介绍一种方法: 以修改环境变量“PATH” ...

  9. startActivityForResult中回调setResult注意事项

    读 http://www.cnblogs.com/lijunamneg/archive/2013/02/05/2892616.html 有感 文中提出了一个核心问题: Android activity ...

  10. java之package与import

    我就以package与import开始吧. package的作用其实就是c++的namespace的作用,防止名字相同的类产生冲突,只是实现的机制不一样,java编译器在编译时,直接根据package ...