LiveMedia收发RTP数据包1
最近的项目需要用Live555架设流媒体服务器,谷歌百度了两天,总算有点进展,小结一下。
目前主流的流媒体服务器有:
1.Helix Server,功能最强大,收费。
2.Darwin Server,稳定,暂无接触。
3.Live555,开源免费,据说性能有瓶颈。
Live555的核心在Live Media,Live Media的核心在Source和Sink。服务器大致的服务流程是调用Sink的continuePlaying()来向客户发送流媒体数据,而continuePlaying()内调用了Source类的getNextFrame()函数,来获取帧数据。简单来说,Source类主要用于获取要发送的数据,而Sink类主要用于发送数据。
一 几个重要的类
1.RTPInterface类
该类的主要作用是从一个Socket读取数据到一个buffer中,是数据的源头所在。
注意到它最重要的一个函数是:Boolean handleRead (unsigned char *buffer, unsigned bufferMaxSize, unsigned &bytesRead, struct sockaddr_in &fromAddress, Boolean &packetReadWasIncomplete),它将fromAddress中的数据读入到buffer中。
2.BufferedPacket类
该类用于存储媒体数据的RTP包内容,它的子类具体到媒体类型,如H264BufferedPacket类。值得注意的有两点:
1)构造函数BufferedPacket()中申请了MAX_PACKET_SIZE(10000)大小的unsigned char数组。
2)一个重要函数是
Boolean fillInData (RTPInterface &rtpInterface, Boolean &packetReadWasIncomplete)
{
rtpInterface.handleRead(&fBuf);
}
实现了将rtpInterface指向的数据存入fBuf中的功能。
4.ReorderingPacketBuffer类
该类用于存放多个BufferedPacket对象(可能是对象指针链表,有待考察),作为Source类中组织多个BufferedPacket对象的场所。
二 Source类的继承关系
Medium<-MediaSource<-FramedSource<-RTPSource<-MultiFramedRTPSource<-H264<-VideoRTPSource
其中,我们要重点关注的类是下面几个:
FramedSource,RTPSource,MultiFramedRTPSource。
1.FramedSource类
class FramedSource
{
void getNextFrame (unsigned char *to,......)
{
......
doGetNextFrame();
}
virtual void doGetNextFrame ()=0;
}
2.RTPSource类
该类并未实现doGetNextFrame()函数,因而getNextFrame()与doGetNextFrame()与FramedSource类中定义完全相同。需要注意该类相比父类FramedSource,其protected成员多了一个RTPInterface fRTPInterface。
3.MultiFramedRTPSource类
非常重要的类,实现了doGetNextFrame()函数。
class MultiFramedRTPSource
{
public:
void getNextFrame (unsigned char *to,......)
{
......
doGetNextFrame();
}
void doGetNextFrame ()
{
......
fRTPInterface.startNetworkReading();
doGetNextFrame1()
{
BufferedPacket* nextPacket = fReorderingBuffer->getNextCompletedPacket();
};
}
void networkReadHandler1 ()
{
......
do
{
bPacket->fillInData(fRTPInterface);
fReorderingBuffer->storePacket(bPacket);
}while(0);
}
protected:
RTPInterface fRTPInterface;
private:
ReorderingPacketBuffer *fReorderingBuffer;
}
三 RTP包的接收以及发送流程
了解了以上几个类以及重要的函数,大概的RTP包处理流程推断如下:某个Sink类调用continuePlaying()函数,而continuePlaying()函数中调用Source类(以MultiFramedRTPSource为例,因为它以实现doGetFrame()函数)的getNextFrame()函数以得到发送数据,而getNextFrame()是通过调用doGetNextFrame(),继而是doGetNextFrame1(),最终在doNextFrame1中由语句fReorderingBuffer->getNextCompletedPacket()将存放在fReorderingBuffer中的数据取出交给Sink类来发送。
那么,fReorderingBuffer中的数据是从何而来呢?推测是通过MultiFramedRTPSource类的networkReadHandler1()函数不断从fRTPInterface所指向的socket读入, 最终执行语句fReorderingBuffer->storePacket(bPacket);实现。