[英]Receiving multicast RTP stream (containing multiple subsessions) from a recorded RTSP session (pcap) using Live555
我必須實現一個 RTSP 客戶端,它連接到現有的 RTSP session 而不能向 RTSP 服務器發送命令(recvonly)。
為了模擬這樣的環境,我使用 Wireshark 在 Live555 的 testH264VideoStreamer 和 testRTSPClient 示例之間記錄了 RTSP/RTP stream,並使用 tcpreplay 播放它,同時嘗試接收 stream 數據和修改版本的 test。
我還將 testH264VideoStreamer 提供的 SDP 信息存儲為 SDP 文件。
v=0
o=- 1606317166144671 1 IN IP4 192.168.3.92
s=Session streamed by "testH264VideoStreamer"
i=test.264
t=0 0
a=tool:LIVE555 Streaming Media v2020.10.16
a=type:broadcast
a=control:*
a=source-filter: incl IN IP4 * 192.168.3.92
a=rtcp-unicast: reflection
a=range:npt=0-
a=x-qt-text-nam:Session streamed by "testH264VideoStreamer"
a=x-qt-text-inf:test.264
m=video 18888 RTP/AVP 96
c=IN IP4 232.42.39.62/255
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=640028;sprop-$
a=control:track1
^@
我修改了 testRTSPClient 示例,使其僅通過使用 SDP 文件中的數據連接到 RTP stream。
這是我用來初始化的兩個函數。
void openSDP(UsageEnvironment& env, char const* sdpFile)
{
const char * rtspURL = "rtsp://192.168.3.92:8554/testStream/";
RTSPClient* rtspClient = ourRTSPClient::createNew(env, rtspURL, RTSP_CLIENT_VERBOSITY_LEVEL);
if(rtspClient == NULL)
{
env << "Failed to create a RTSP client for URL \"" << rtspURL << "\": " << env.getResultMsg();
return;
}
else
{
env << "Connecting to the stream at " << rtspURL;
}
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
std::vector<char> sdpBuffer;
std::ifstream file(sdpFile, std::ios_base::in | std::ios_base::binary);
file.unsetf(std::ios::skipws);
std::streampos fileSize;
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
sdpBuffer.reserve(fileSize);
sdpBuffer.insert(sdpBuffer.begin(),
std::istream_iterator<unsigned char>(file),
std::istream_iterator<unsigned char>());
char* const sdpDescription = sdpBuffer.data();
// Create a media session object from this SDP description:
scs.session = MediaSession::createNew(env, sdpDescription);
if(scs.session == NULL)
{
env << *rtspClient << "Failed to create a MediaSession object from the SDP description: " << env.getResultMsg() << "\n";
}
else
if(!scs.session->hasSubsessions())
{
env << *rtspClient << "This session has no media subsessions (i.e., no \"m=\" lines)\n";
}
scs.iter = new MediaSubsessionIterator(*scs.session);
setupNextSubsession(rtspClient);
return;
}
void setupNextSubsession(RTSPClient* rtspClient)
{
UsageEnvironment& env = rtspClient->envir(); // alias
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
scs.subsession = scs.iter->next();
if(scs.subsession != NULL)
{
if(!scs.subsession->initiate())
{
env << "Failed to initiate the subsession: " << env.getResultMsg();
setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
}
else
{
env << "Initiated the subsession:";
if(scs.subsession->rtcpIsMuxed())
{
env << "client port " << scs.subsession->clientPortNum();
}
else
{
env << "client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1;
}
scs.subsession->sink = DummySink::createNew(env,
*scs.subsession,
rtspClient->url());
// perhaps use your own custom "MediaSink" subclass instead
if(scs.subsession->sink == NULL)
{
env << "Failed to create a data sink for the subsession: " << env.getResultMsg();
}
env << "Created a data sink for the subsession";
scs.subsession->miscPtr = rtspClient; // a hack to let subsession handler functions get the "RTSPClient" from the subsession
scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
subsessionAfterPlaying, scs.subsession);
// Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
if(scs.subsession->rtcpInstance() != NULL)
{
scs.subsession->rtcpInstance()->setByeWithReasonHandler(subsessionByeHandler, scs.subsession);
}
// Set up the next subsession, if any:
setupNextSubsession(rtspClient);
}
}
}
一切初始化都沒有錯誤,但 DummySink 沒有收到任何數據。 有任何想法嗎?
我發現雖然wireshark 向我顯示了帶有有效校驗和的傳入數據包,但udp 端口沒有收到任何數據包。
我嘗試了以下命令(作為 sudo)來避免 kernel 丟棄數據包,但它們對 Debian Buster 沒有幫助。
sysctl net.ipv4.conf.eth0.rp_filter=0
sysctl net.ipv4.conf.all.rp_filter=0
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
sysctl -a | grep "\.rp_filter" | awk '{print $1 "=0"}' | xargs sysctl
基本上我已經從另一台計算機流式傳輸 pcap 文件,現在我能夠接收 NALU。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.