live555讀檔案改為記憶體讀取實現
最近遇到有人問live555視訊直播的問題,剛好前段時間接觸過,這個功能可以通過讀記憶體資料實現;
具體實現方式是參考的這篇文章思路,可以先了解一下看看:
http://blog.chinaunix.net/uid-15063109-id-132142.html
live555原始碼裡面有一個讀檔案的測試demo,live555mediaserver,本文修改這份原始碼實現讀記憶體直播功能;
首先先了解一下live555資料流和live555mediaserver demo中的函式呼叫層次,以H264為例:
由以上兩個圖可知,要想實現直播功能,有兩個方案:
1)修改BypteStreamFileSource類中的 讀取檔案程式碼,改成從記憶體中讀取,這個方案修改最簡單,但是會破壞Live555框架的原始碼
2)參考BypteStreamFileSource寫一個ByteStreamLiveSource,修改讀檔案部分;
由於source是由H264VideoFileServerMediaSubsession建立並呼叫的,所以要同步新建一個H264VideoLiveServerMediaSubsession類
這裡只討論第二種方案,下面看程式碼:
1)DynamicRTSPServer.cpp
} 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: 原始檔無法執行,僅供參考