日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LIVE555再学习 -- testRTSPClient 实例

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LIVE555再学习 -- testRTSPClient 实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇文章簡單看了一遍?testRTSPClient ?的源碼,接下來舉幾個應用實例加深一下。

首先什么都不做修改,先執行一遍,看一下。

一、執行?testRTSPClient ?



特么,上面的東西我沒看明白。。。 a=、b=、c=等等這是什么?

還有我看別人分析的好像用到什么網絡抓包工具,我不知道是什么工具,可能是 Wireshark ,我也不曉得怎么用。

參看: live555源代碼分析

二、核心代碼

再就是做移植的時候主要更改的地方


上述函數中會返回每幀數據長度 frameSize,fReceiveBuffer 是緩存指針;
DUMMY_SINK_RECEIVE_BUFFER_SIZE宏值默認是100000,若是高清視頻超過1080p需要設置為300000。
一般為了取流我們必須在此觸發個回調函數將frameSize,fReceiveBuffer以參數化形式送出。
fSubsession為媒體信息,主要提供通道名稱、RTP負載類型、RTP時間戳、序列等信息,很重要的信息,可用于區分音、視頻。
DummySink為數據池,用于處理攝像機發送過來的視頻流。

三、實例(1)

參看:live555 使用testRTSPClient 接收h264記錄

接收 h264 文件記錄

void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned /*durationInMicroseconds*/) { // We've just received a frame of data. (Optionally) print out information about it: #ifdef DEBUG_PRINT_EACH_RECEIVED_FRAME if (fStreamId != NULL) envir() << "Stream \"" << fStreamId << "\"; "; envir() << fSubsession.mediumName() << "/" << fSubsession.codecName() << ":\tReceived " << frameSize << " bytes"; if (numTruncatedBytes > 0) envir() << " (with " << numTruncatedBytes << " bytes truncated)"; char uSecsStr[6+1]; // used to output the 'microseconds' part of the presentation time sprintf(uSecsStr, "%06u", (unsigned)presentationTime.tv_usec); envir() << ".\tPresentation time: " << (unsigned)presentationTime.tv_sec << "." << uSecsStr; if (fSubsession.rtpSource() != NULL && !fSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP()) { envir() << "!"; // mark the debugging output to indicate that this presentation time is not RTCP-synchronized } envir() << "\n"; #endif //todo one frame //save to file if(!strcmp(fSubsession.mediumName(), "video")) { if(firstFrame) { unsigned int num; SPropRecord *sps = parseSPropParameterSets(fSubsession.fmtp_spropparametersets(), num); // For H.264 video stream, we use a special sink that insert start_codes: struct timeval tv= {0,0}; unsigned char start_code[4] = {0x00, 0x00, 0x00, 0x01}; FILE *fp = fopen("test.264", "a+b"); if(fp) { fwrite(start_code, 4, 1, fp); fwrite(sps[0].sPropBytes, sps[0].sPropLength, 1, fp); fwrite(start_code, 4, 1, fp); fwrite(sps[1].sPropBytes, sps[1].sPropLength, 1, fp); fclose(fp); fp = NULL; } delete [] sps; firstFrame = False; } char *pbuf = (char *)fReceiveBuffer; char head[4] = {0x00, 0x00, 0x00, 0x01}; FILE *fp = fopen("test.264", "a+b"); if(fp) { fwrite(head, 4, 1, fp); fwrite(fReceiveBuffer, frameSize, 1, fp); fclose(fp); fp = NULL; } } // Then continue, to request the next frame of data: continuePlaying(); }

先理解關鍵知識點,不知道有沒有誤導,H264 的幀是以 NAL 單元的單位來傳送的,一個 NAL 單元包含一幀(I幀 或 P幀 或 B幀),這三種類型的幀可以百度。所謂的 NAL 單元就是去掉 SPS、PPS 的視頻幀, I 幀是關鍵幀,所有的解析都需要靠它,兩個 I 幀之間被稱為視頻序列,I 幀頭部需要加入 SPS 和 PPS,這兩個之間需要 0x00000001 來分割, 0x00 0x00 0x00 0x01 + SPS的 Base64 解碼形式 + 0x00 0x00 0x00 0x01 + PPS 的解碼形式 + 0x00 0x00 0x00 0x01 視頻幀(IDR幀) 這樣組成的一個 buffer,FFMPEG 的 H264 解碼器才能成功解碼。

四、實例(2)

參看:【rtsp錄制器】testRTSPClient+mp4v2錄制mp4(h264+aac)

實現效果為:?
修改 testRTSPClient 來接收音視頻流,并通過mp4v2 將音視頻流錄制為mp4(audio:aac,video:h264)

live555 和 MP4v2 我們之前都講過的,這就簡單了。

參看:mp4v2再學習 -- H264視頻編碼成MP4文件

參看:LIVE555再學習 -- Windows 下編譯

因為我用的是vs2017,直接下載參看博客提供的工程會出現錯誤。

1>------ 已啟動生成: 項目: testRTSPClient, 配置: Debug Win32 ------ 1>TRACKER : 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\Microsoft.Cpp.Win32.Targets(153,5):error MSB6006: “CL.exe”已退出,代碼為 5。 1>已完成生成項目“testRTSPClient.vcxproj”的操作 - 失敗。 ========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ========== 而且需要的庫文件也不是vs2017生成的,容易產生版本不兼容。

得了還是自己從新做一遍。

(1)新建項目

打開 VS; 文件->新建->項目->Win32控制臺應用程序->選擇空項目,點擊完成。 注意,選擇的位置最好不要有 空格或者漢字。

(2)拷貝文件

將 live555 四個庫文件的include 和 lib 拷貝到一起。將MP4v2的include和lib拷貝到一起。

然后將參看博客工程里的 testRTSPClient 文件夾下的 .cpp 和 .h 文件拷貝到新建項目下。?

其中源碼部分也要注意要和存放位置一致




根據實際需要修改你的位置

?


然后將 .h 添加到頭文件刷選器下,將.cpp添加到源文件刷選器下


(3)配置屬性

打開屬性面板

解決方案資源管理器->右鍵單擊項目->屬性


頭文件配置

配置屬性->C/C++->常規->附加包含目錄,輸入
?..\MP4Encoder\include;..\live555\BasicUsageEnvironment\include;..\live555\groupsock\include;..\live555\liveMedia\include;..\live555\UsageEnvironment\include


導入庫配置

配置屬性->鏈接器->常規->附加庫目錄,輸入?..\MP4Encoder\lib


配置屬性->鏈接器->輸入->附加依賴項,輸入?libmp4v2.lib;

live555 四個庫,用程序包含了,這里就不用再添加了。

#pragma comment (lib, "Ws2_32.lib") #pragma comment(lib,"../live555/lib/BasicUsageEnvironment.lib") #pragma comment(lib,"../live555/lib/liveMedia.lib") #pragma comment(lib,"../live555/lib/groupsock.lib") #pragma comment(lib,"../live555/lib/UsageEnvironment.lib")



此刻再編譯testRTSPClient,OK 編譯成功,生成 testRTSPClient.exe。


(4)測試

打開live555服務器


執行?testRTSPClient.exe rtsp://192.168.2.xx/Titanic.mkv


最后生成?lsh.mp4,將其和?Titanic.mkv 對比。可發現比?Titanic.mkv 小了十幾 KB。


使用 VLC 播放?lsh.mp4 ,沒有聲音.?


(5)項目工程

下載:testRTSPClient+mp4v2錄制mp4工程文件

(6)總結

這個工程,源碼部分,還好理解。核心源碼

void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned /*durationInMicroseconds*/) {// We've just received a frame of data. (Optionally) print out information about it: #ifdef DEBUG_PRINT_EACH_RECEIVED_FRAMEif (fStreamId != NULL) envir() << "Stream \"" << fStreamId << "\"; ";envir() << fSubsession.mediumName() << "/" << fSubsession.codecName() << ":\tReceived " << frameSize << " bytes";if (numTruncatedBytes > 0) envir() << " (with " << numTruncatedBytes << " bytes truncated)";char uSecsStr[6+1]; // used to output the 'microseconds' part of the presentation timesprintf(uSecsStr, "%06u", (unsigned)presentationTime.tv_usec);envir() << ".\tPresentation time: " << (int)presentationTime.tv_sec << "." << uSecsStr;if (fSubsession.rtpSource() != NULL && !fSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP()) {envir() << "!"; // mark the debugging output to indicate that this presentation time is not RTCP-synchronized} #ifdef DEBUG_PRINT_NPTenvir() << "\tNPT: " << fSubsession.getNormalPlayTime(presentationTime); #endifenvir() << "\n"; #endif//----------------------------------------------------------------------------------static int count = 1;//if(count++ == 6000){m_mp4Encoder->CloseMp4Encoder();MessageBoxA(NULL,"end","end",MB_OK);}//if ( 0==strcmp(fSubsession.mediumName(),"video") ) {m_recvBuf[0] = 0x00;m_recvBuf[1] = 0x00;m_recvBuf[2] = 0x00;m_recvBuf[3] = 0x01;//if(m_isInitSpsPps){m_isInitSpsPps = false;unsigned int num=0; SPropRecord * sps=parseSPropParameterSets(fSubsession.fmtp_spropparametersets(),num);//for(int i=0;i<2;i++){memcpy(&m_recvBuf[4], sps[i].sPropBytes, sps[i].sPropLength);m_mp4Encoder->Mp4VEncode(m_recvBuf,sps[i].sPropLength+4);}delete[] sps; }//memcpy(&m_recvBuf[4], fReceiveBuffer, frameSize);m_mp4Encoder->Mp4VEncode(m_recvBuf,frameSize+4);}if ( 0==strcmp(fSubsession.mediumName(),"audio") ){memcpy(m_recvBuf,fReceiveBuffer,frameSize);m_mp4Encoder->Mp4AEncode(m_recvBuf,frameSize);}//----------------------------------------------------------------------------------// Then continue, to request the next frame of data:continuePlaying(); }

MP4v2部分的源碼,我就不曉得了。跟我之前參看的?mp4v2再學習 -- H264視頻編碼成MP4文件?不太一樣

然后,我又想一般我們都是 sensor 輸出數據然后通過 RTSP 傳輸 VLC 播放,是這樣的一套。

這個?testRTSPClient RTSP的客戶端肯定是不對的。應該是 RTSP的服務器測。

所以,接下來我們講下一個源碼分析之?testH264VideoStreamer,官網介紹如下:

testH264VideoStreamer?repeatedly reads from a H.264 Elementary Stream video file (named "test.264"), and streams it using RTP multicast. This program also has a built-in RTSP server.

  • Apple's "QuickTime Player" can be used to receive and play this audio stream. To use this, have the player open the session's "rtsp://" URL (which the program prints out as it starts streaming).
  • The Open Source "VLC" and "MPlayer" media players can also be used.

翻譯一下:

testH264VideoStreamer 重復從 H.264 基本流視頻文件(名為“test.264”)中讀取,并使用 RTP 多播進行流式傳輸。 該程序還具有內置的 RTSP 服務器。
Apple 的“QuickTime 播放器”可用于接收和播放此音頻流。 要使用它,讓玩家打開會話的“rtsp://”URL(程序在開始流式傳輸時打印出來)。
開源“VLC”和“MPlayer”媒體播放器也可以使用。



總結

以上是生活随笔為你收集整理的LIVE555再学习 -- testRTSPClient 实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。