live555读文件改为内存读取实现

        最近遇到有人问live555视频直播的问题,刚好前段时间接触过,这个功能可以通过读内存数据实现;

        具体实现方式是参考的这篇文章思路,可以先了解一下看看:

        http://blog.chinaunix.net/uid-15063109-id-132142.html

        

        live555源码里面有一个读文件的测试demo,live555mediaserver,本文修改这份源码实现读内存直播功能;

        首先先了解一下live555数据流和live555mediaserver demo中的函数调用层次,以H264为例:

live555读文件改为内存读取实现_第1张图片

        由以上两个图可知,要想实现直播功能,有两个方案:

        1)修改BypteStreamFileSource类中的 读取文件代码,改成从内存中读取,这个方案修改最简单,但是会破坏Live555框架的源码

        2)参考BypteStreamFileSource写一个ByteStreamLiveSource,修改读文件部分; 

由于source是由H264VideoFileServerMediaSubsession创建并调用的,所以要同步新建一个H264VideoLiveServerMediaSubsession类

        这里只讨论第二种方案,下面看代码:

        1)DynamicRTSPServer.cpp 中 createNewSMS函数:

  } else if (strcmp(extension, ".264") == 0) {
    // Assumed to be a H.264 Video Elementary Stream file:
    NEW_SMS("H.264 Video");
    OutPacketBuffer::maxSize = 100000; // allow for some possibly large H.264 frames
    sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
  } else if (strcmp(extension, ".265") == 0) {

         上面的代码就是根据RTSP请求中文件名的后缀调用不同的码流解析类,由于我们新建了一个 H264VideoLiveServerMediaSubsession 类,这里要改成

sms->addSubsession(H264VideoLiveServerMediaSubsession::createNew(env, fileName, reuseSource));

         2)修改H264VideoLiveServerMediaSubsession类修改createNewStreamSource函数

FramedSource* H264VideoLiveServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate)
{
	/* Remain to do : assign estBitrate */
	estBitrate = 1000; // kbps, estimate

	// Create the video source:
	ByteStreamLiveSource* liveSource = ByteStreamLiveSource::createNew(envir(), fFileName);
	//ByteStreamFileSource* liveSource = ByteStreamFileSource::createNew(envir(), fFileName);
	if (liveSource == NULL)
	{
		return NULL;
	}

	// Create a framer for the Video Elementary Stream:
	return H264VideoStreamFramer::createNew(envir(), liveSource);
}

        3)ByteStreamLiveSource修改

void ByteStreamFileSource::doGetNextFrame() {
  if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {
    handleClosure();
    return;
  }

#ifdef READ_FROM_FILES_SYNCHRONOUSLY
  doReadFromFile();
#else
  if (!fHaveStartedReading) {
    // Await readable data from the file:
    envir().taskScheduler().turnOnBackgroundReadHandling(fileno(fFid),
	       (TaskScheduler::BackgroundHandlerProc*)&fileReadableHandler, this);
    fHaveStartedReading = True;
  }
#endif
}
上面ByteStreamFileSource是读取文件代码,只要在新建的ByteStreamLiveSource为中添加一个doReadFromBuffer函数,实现从内存中读取功能,然后替换掉doReadFromFile函数就OK了,像这样:

void ByteStreamLiveSource::doGetNextFrame() {
// 	if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {
// 		handleClosure();
// 		return;
// 	}

#ifdef READ_FROM_FILES_SYNCHRONOUSLY
	doReadFromBuffer();
#else
	if (!fHaveStartedReading) {
		// Await readable data from the file:
		envir().taskScheduler().turnOnBackgroundReadHandling(fileno(fFid),
			(TaskScheduler::BackgroundHandlerProc*)&fileReadableHandler, this);
		fHaveStartedReading = True;
	}
#endif
}
        doReadFromBuffer需要拷贝码流数据到 fTo 缓冲区,实现也比较简单,这里就不写了。


        H264VideoLiveServerMediaSubsession类和ByteStreamLiveSource类源文件地址:  

        http://download.csdn.net/detail/lifexx/9654860

        ps: 源文件无法执行,仅供参考

你可能感兴趣的:(多媒体)