您的位置:首页 > 其它

对live555封装的比较好的一个类,网上找到的,觉得不错,给大家共享

2014-12-31 17:19 761 查看
对live555封装的比较好的一个类,网上找到的,觉得不错,给大家共享,也不记得从哪里下载的了,版权归原作者!

 

这个类的主要特点是可以创建多个客户端,连接多路码流;我们可以参考他的设计,在sink中将码流回调出来,在外部解码;

 

文件如下:

#pragma once

#include "BasicUsageEnvironment\BasicUsageEnvironment.hh"
#include "groupsock\GroupsockHelper.hh"
#include "liveMedia\liveMedia.hh"
#include <iostream>
#include <list>
#include <map>

struct YHRTSPClient
{
TaskScheduler* pTaskScheduler;
UsageEnvironment* pEnv;
RTSPClient* pClient;
MediaSession *pMediaSession;
MediaSubsessionIterator *iter;
Boolean bMadeProgress;
unsigned fileSinkBufferSize;
unsigned socketInputBufferSize;
Boolean  bStreamUsingTCP;
Authenticator* pAuthenticator;
char	 m_cEventLoop;
YHRTSPClient()
{
pClient = NULL;
pMediaSession = NULL;
iter = NULL;
bMadeProgress = False;
fileSinkBufferSize = 100000;
socketInputBufferSize = 524288;
bStreamUsingTCP = False;
pAuthenticator = NULL;
m_cEventLoop = 0;

}
YHRTSPClient(RTSPClient *client)
{
pClient = client;
pMediaSession = NULL;
iter = NULL;
bMadeProgress = False;
fileSinkBufferSize = 100000;
socketInputBufferSize = 524288;
bStreamUsingTCP = False;
pAuthenticator = NULL;
m_cEventLoop = 0;
}
};

class CYHMediaClient
{
public:
static CYHMediaClient* GetInstance();
CYHMediaClient(void);
~CYHMediaClient(void);
public:
BOOL CreateRTPClient(LONG lID, const char *chServerURL);
//BOOL StartStreaming(char *chWatchVariable = NULL);
void StopStreaming(int nClientID);

void GetSDPDescription(RTSPClient* pRTSPClient, RTSPClient::responseHandler* afterFunc);
void SetupStreams(RTSPClient* pRTSPClient);
void SetupSubsession(RTSPClient* pRTSPClient,MediaSubsession* subsession, Boolean streamUsingTCP, RTSPClient::responseHandler* afterFunc);
void StartPlayingSession(RTSPClient* pRTSPClient,MediaSession* session, double start, double end, float scale, RTSPClient::responseHandler* afterFunc);
void TearDownSession(RTSPClient* pRTSPClient,MediaSession* session, RTSPClient::responseHandler* afterFunc);

void SetFileSinkAndSocket(YHRTSPClient *pYHClient,unsigned fileSinkBufferSize,unsigned socketInputBufferSize);
void SetStreamUsingTCP(YHRTSPClient* pYHClient, Boolean bStreamUsingTCP){pYHClient->bStreamUsingTCP = bStreamUsingTCP;};

UsageEnvironment *GetEnvironment(RTSPClient* pRTSPClient)
{
UsageEnvironment *pEnv = NULL;
if (NULL == pRTSPClient)
{
return pEnv;
}
YHRTSPClient *pYHClient = GetYHRTSPClient(pRTSPClient);
if (NULL != pYHClient)
{
pEnv = pYHClient->pEnv;
}

return pEnv;
};

private:
void GetOptions(RTSPClient* pRTSPClient, RTSPClient::responseHandler* afterFunc);
void Shutdown(RTSPClient *pClient = NULL);
YHRTSPClient* GetYHRTSPClient(RTSPClient *pClient);
void EraseYHRTSPClient(RTSPClient *pClient);
LONG GetRTSPClientID(RTSPClient* pClient);
void CloseMediaSinks(RTSPClient *pClient);

static void ContinueAfterOptions(RTSPClient* pClient, int resultCode, char* resultString);
static void ContinueAfterDescribe(RTSPClient* pClient, int resultCode, char* resultString);
static void ContinueAfterSetup(RTSPClient* pClient, int resultCode, char* resultString);
static void ContinueAfterPlay(RTSPClient* pClient, int resultCode, char* resultString);
static void SubsessionAfterPlaying(void* clientData);
static void SubsessionByeHandler(void* clientData);
static void ContinueAfterTearDown(RTSPClient* pClient, int resultCode, char* resultString) ;

public:
std::list<YHRTSPClient*> m_listRTSPClient;
std::map<int, RTSPClient*> m_mapClientID;
private:
static CYHMediaClient* pYHMediaClient;
//TaskScheduler* pTaskScheduler;
//UsageEnvironment* pEnv;
};

源文件如下:
<pre class="cpp" name="code">//#include "stdafx.h"
#include "YHMediaClient.h"
#include "WinCriticalSection.h"
#include "MetMediaSink.h"
//#include "YHWMPlayDemoDlg.h"
char const* clientProtocolName = "RTSP";
CYHMediaClient* CYHMediaClient::pYHMediaClient = NULL;
WinCriticalSection g_cs;

CYHMediaClient* CYHMediaClient::GetInstance()
{
Mutex mutex(g_cs);
if (CYHMediaClient::pYHMediaClient == NULL)
{
pYHMediaClient = new CYHMediaClient;
}
return pYHMediaClient;
}

CYHMediaClient::CYHMediaClient(void)
{

}

CYHMediaClient::~CYHMediaClient(void)
{
m_listRTSPClient.empty();
}

BOOL CYHMediaClient::CreateRTPClient(LONG lID, const char *chServerURL)
{
g_cs.Enter();
TaskScheduler *pTaskScheduler = BasicTaskScheduler::createNew();
UsageEnvironment *pEnv = BasicUsageEnvironment::createNew(*pTaskScheduler);
RTSPClient* pRTSPClient = (RTSPClient*)RTSPClient::createNew(*pEnv, chServerURL, 0, NULL, 0);
if (NULL == pRTSPClient)
{
*pEnv << "Failed to create" << clientProtocolName << " client: " << pEnv->getResultMsg() << "\n";
return FALSE;
}
m_mapClientID.insert(std::make_pair(lID, pRTSPClient));
YHRTSPClient *stucClient = new YHRTSPClient(pRTSPClient);
stucClient->pTaskScheduler = pTaskScheduler;
stucClient->pEnv = pEnv;
CYHMediaClient::GetInstance()->m_listRTSPClient.push_back(stucClient);
GetOptions(pRTSPClient, ContinueAfterOptions);
g_cs.Leave();
stucClient->pEnv->taskScheduler().doEventLoop(&stucClient->m_cEventLoop);
if (pTaskScheduler)
{
delete pTaskScheduler;
pTaskScheduler = NULL;
}
if(stucClient)
{
delete stucClient;
stucClient = NULL;
}
return TRUE;
}

void CYHMediaClient::StopStreaming(int nClientID)
{
Mutex mutex(g_cs);
std::map<int, RTSPClient*>::iterator iter = m_mapClientID.find(nClientID);
if (iter != m_mapClientID.end())
{
RTSPClient* pRTSPClient = iter->second;
Shutdown(pRTSPClient);
EraseYHRTSPClient(pRTSPClient);
m_mapClientID.erase(iter);
}
}

void CYHMediaClient::Shutdown(RTSPClient *pClient)
{
YHRTSPClient* pYHRTSPClient = GetYHRTSPClient(pClient);
if (pYHRTSPClient != NULL)
{
if (pYHRTSPClient->pMediaSession != NULL)
{
TearDownSession(pClient,pYHRTSPClient->pMediaSession, ContinueAfterTearDown);
}
else
{
ContinueAfterTearDown(NULL, 0, NULL);
}
CYHMediaClient::GetInstance()->CloseMediaSinks(pClient);
if (pYHRTSPClient->pMediaSession)
{
Medium::close(pYHRTSPClient->pMediaSession);
pYHRTSPClient->pMediaSession = NULL;
}
// Finally, shut down our client:
if (pClient)
{
Medium::close(pClient);
pClient = NULL;
}
pYHRTSPClient->m_cEventLoop = 1;

}

}

void CYHMediaClient::GetOptions(RTSPClient* pRTSPClient, RTSPClient::responseHandler* afterFunc)
{
Mutex mutex(g_cs);
if (pRTSPClient)
{
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pRTSPClient);
pRTSPClient->sendOptionsCommand(afterFunc, pYHClient->pAuthenticator);
}
}

void CYHMediaClient::GetSDPDescription(RTSPClient* pRTSPClient,RTSPClient::responseHandler* afterFunc)
{
Mutex mutex(g_cs);
if (pRTSPClient)
{
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pRTSPClient);
pRTSPClient->sendDescribeCommand(afterFunc, pYHClient->pAuthenticator);
}
}

void CYHMediaClient::SetupSubsession(RTSPClient* pRTSPClient,MediaSubsession* subsession, Boolean streamUsingTCP, RTSPClient::responseHandler* afterFunc)
{
Mutex mutex(g_cs);
Boolean forceMulticastOnUnspecified = False;
if (pRTSPClient)
{
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pRTSPClient);
pRTSPClient->sendSetupCommand(*subsession, afterFunc, False, streamUsingTCP, forceMulticastOnUnspecified, pYHClient->pAuthenticator);
}
}

void CYHMediaClient::StartPlayingSession(RTSPClient* pRTSPClient,MediaSession* session, double start, double end, float scale, RTSPClient::responseHandler* afterFunc)
{
//Mutex mutex(g_cs);
if (pRTSPClient)
{
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pRTSPClient);
pRTSPClient->sendPlayCommand(*session, afterFunc, start, end, scale, pYHClient->pAuthenticator);
}
}

void CYHMediaClient::TearDownSession(RTSPClient* pRTSPClient,MediaSession* session, RTSPClient::responseHandler* afterFunc)
{
Mutex mutex(g_cs);
if (pRTSPClient)
{
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pRTSPClient);
pRTSPClient->sendTeardownCommand(*session, afterFunc, pYHClient->pAuthenticator);
}
}

void CYHMediaClient::ContinueAfterOptions(RTSPClient* pClient, int resultCode, char* resultString)
{
Mutex mutex(g_cs);
if(CYHMediaClient::GetInstance() != NULL)
{
if (resultCode != 0)
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << clientProtocolName << " \"OPTIONS\" request failed: " << resultString << "\n";
return;
}
else
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << clientProtocolName << " \"OPTIONS\" request returned: " << resultString << "\n";
}
delete[] resultString;

CYHMediaClient::GetInstance()->GetSDPDescription(pClient, ContinueAfterDescribe);
}
return;
}

void CYHMediaClient::ContinueAfterDescribe(RTSPClient* pClient, int resultCode, char* resultString)
{
Mutex mutex(g_cs);
if (CYHMediaClient::GetInstance() != NULL)
{
if (resultCode != 0)
{
CYHMediaClient::GetInstance()->Shutdown();
return;
}

char* sdpDescription = resultString;
// Create a media session object from this SDP description:
MediaSession *pMediaSession = MediaSession::createNew(*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)), sdpDescription);
delete[] sdpDescription;

if (pMediaSession == NULL)
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << "Failed to create a MediaSession object from the SDP description: " << CYHMediaClient::GetInstance()->GetEnvironment(pClient)->getResultMsg() << "\n";
CYHMediaClient::GetInstance()->Shutdown(pClient);
return;
}
else if (!pMediaSession->hasSubsessions())
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << "This session has no media subsessions (i.e., \"m=\" lines)\n";
CYHMediaClient::GetInstance()->Shutdown(pClient);
return;
}

// Then, setup the "RTPSource"s for the session:
MediaSubsessionIterator iter(*pMediaSession);

MediaSubsession *subsession;
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pClient);
pYHClient->bMadeProgress = False;
pYHClient->pMediaSession = pMediaSession;

while ((subsession = iter.next()) != NULL)
{
if (!subsession->initiate())
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << "Unable to create receiver for \"" << subsession->mediumName()
<< "/" << subsession->codecName()
<< "\" subsession: " << CYHMediaClient::GetInstance()->GetEnvironment(pClient)->getResultMsg() << "\n";
}
else
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << "Created receiver for \"" << subsession->mediumName()
<< "/" << subsession->codecName()
<< "\" subsession (client ports " << subsession->clientPortNum()
<< "-" << subsession->clientPortNum()+1 << ")\n";

pYHClient->bMadeProgress = True;
if (subsession->rtpSource() != NULL)
{
// Because we're saving the incoming data, rather than playing
// it in real time, allow an especially large time threshold
// (1 second) for reordering misordered incoming packets:
unsigned const thresh = 500000; // 0.5 second
subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);

// Set the RTP source's OS socket buffer size as appropriate - either if we were explicitly asked (using -B),
// or if the desired FileSink buffer size happens to be larger than the current OS socket buffer size.
// (The latter case is a heuristic, on the assumption that if the user asked for a large FileSink buffer size,
// then the input data rate may be large enough to justify increasing the OS socket buffer size also.)
int socketNum = subsession->rtpSource()->RTPgs()->socketNum();
unsigned curBufferSize = getReceiveBufferSize(*CYHMediaClient::GetInstance()->GetEnvironment(pClient), socketNum);
if (pYHClient->socketInputBufferSize > 0 || pYHClient->fileSinkBufferSize > curBufferSize)
{
unsigned newBufferSize = pYHClient->socketInputBufferSize > 0 ? pYHClient->socketInputBufferSize : pYHClient->fileSinkBufferSize;
newBufferSize = setReceiveBufferTo(*CYHMediaClient::GetInstance()->GetEnvironment(pClient), socketNum, newBufferSize);
}
}
}
}
if (!pYHClient->bMadeProgress)
{
CYHMediaClient::GetInstance()->Shutdown(pClient);
return;
}

// Perform additional 'setup' on each subsession, before playing them:
CYHMediaClient::GetInstance()->SetupStreams(pClient);
}
}

void CYHMediaClient::SetupStreams(RTSPClient* pRTSPClient)
{
Mutex mutex(g_cs);
YHRTSPClient *struClient = GetYHRTSPClient(pRTSPClient);
if (struClient->iter == NULL)
struClient->iter = new MediaSubsessionIterator(*(struClient->pMediaSession));
MediaSubsession *subsession = NULL;
while ((subsession = struClient->iter->next()) != NULL)
{
// We have another subsession left to set up:
if (subsession->clientPortNum() == 0)
continue; // port # was not set
if (pRTSPClient != NULL)
{
SetupSubsession(pRTSPClient, subsession, /*struClient->bStreamUsingTCP*/True, ContinueAfterSetup);
}
return;
}

// We're done setting up subsessions.
if (!struClient->bMadeProgress)
{
Shutdown(pRTSPClient);
return;
}

// Create and start "FileSink"s for each subsession:
struClient->bMadeProgress = False;
MediaSubsessionIterator iter(*(struClient->pMediaSession));
while ((subsession = iter.next()) != NULL)
{
if (subsession->readSource() == NULL)
continue; // was not initiated

// Create an output file for each desired stream:
CMetMediaSink* pMediaSink;
unsigned int requestedBufferSize = 524288;
pMediaSink = CMetMediaSink::createNew(*struClient->pEnv, struClient->socketInputBufferSize);
pMediaSink->SetMediaSession(struClient->pMediaSession);
pMediaSink->SetPlayHandle(GetRTSPClientID(pRTSPClient));
subsession->sink = pMediaSink;
if (subsession->sink == NULL)
{
*struClient->pEnv << "Failed to create MediaSink for \"" << "MediaClient"<< "\": " << struClient->pEnv->getResultMsg() << "\n";
}
else
{
subsession->sink->startPlaying(*(subsession->readSource()),SubsessionAfterPlaying,subsession);

// Also set a handler to be called if a RTCP "BYE" arrives
// for this subsession:
if (subsession->rtcpInstance() != NULL)
{
subsession->rtcpInstance()->setByeHandler(SubsessionByeHandler, subsession);
}
struClient->bMadeProgress = True;
}
}
if (!struClient->bMadeProgress)
{
Shutdown(pRTSPClient);
return;
}
double duration = 0;
YHRTSPClient* pYHRTSPClient = GetYHRTSPClient(pRTSPClient);
duration = pYHRTSPClient->pMediaSession->playEndTime();
if (duration < 0)
duration = 0.0;

double dwEnd = duration;
StartPlayingSession(pRTSPClient,pYHRTSPClient->pMediaSession, 0, dwEnd, 1.0, ContinueAfterPlay);
}

void CYHMediaClient::ContinueAfterSetup(RTSPClient* pClient, int resultCode, char* resultString)
{
Mutex mutex(g_cs);
if (pClient == NULL)
{
return;
}

if (CYHMediaClient::GetInstance() != NULL)
{
if (resultCode == 0)
{
YHRTSPClient *pYHClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pClient);
pYHClient->bMadeProgress = True;
}
// Set up the next subsession, if any:
CYHMediaClient::GetInstance()->SetupStreams(pClient);
}
}

void CYHMediaClient::ContinueAfterPlay(RTSPClient* pClient, int resultCode, char* resultString)
{
Mutex mutex(g_cs);
if (CYHMediaClient::GetInstance() != NULL)
{
if (resultCode != 0)
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << "Failed to start playing session: " << resultString << "\n";
CYHMediaClient::GetInstance()->Shutdown(pClient);
return;
}
else
{
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << "Started playing session\n";
}
char const* actionString ="Receiving streamed data...";
*(CYHMediaClient::GetInstance()->GetEnvironment(pClient)) << actionString << "...\n";
}
}

void CYHMediaClient::SubsessionAfterPlaying(void* clientData)
{
Mutex mutex(g_cs);
MediaSubsession* subsession = (MediaSubsession*)clientData;
Medium::close(subsession->sink);
subsession->sink = NULL;
}

void CYHMediaClient::SubsessionByeHandler(void* clientData)
{
Mutex mutex(g_cs);
MediaSubsession* subsession = (MediaSubsession*)clientData;
if (subsession != NULL)
{
// Act now as if the subsession had closed:
SubsessionAfterPlaying(subsession);
}
}

void CYHMediaClient::ContinueAfterTearDown(RTSPClient* pClient, int resultCode, char* resultString)
{
/*
Mutex mutex(g_cs);
// Now that we've stopped any more incoming data from arriving, close our output files:
if (CYHMediaClient::GetInstance()!= NULL)
{
CYHMediaClient::GetInstance()->CloseMediaSinks(pClient);
YHRTSPClient *struClient = CYHMediaClient::GetInstance()->GetYHRTSPClient(pClient);
if (struClient->pMediaSession)
{
Medium::close(struClient->pMediaSession);
}
// Finally, shut down our client:
if (struClient->pAuthenticator)
{
delete struClient->pAuthenticator;
}
Medium::close(pClient);
struClient->m_cEventLoop = 1;
}*/

}

void CYHMediaClient::CloseMediaSinks(RTSPClient *pClient)
{
YHRTSPClient* pYHRTSPClient = GetYHRTSPClient(pClient);
if (pYHRTSPClient->pMediaSession == NULL)
return;
MediaSubsessionIterator iter(*pYHRTSPClient->pMediaSession);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL)
{
Medium::close(subsession->sink);
subsession->sink = NULL;
}
}

YHRTSPClient* CYHMediaClient::GetYHRTSPClient(RTSPClient *pClient)
{
if (m_listRTSPClient.size() == 0)
{
return NULL;
}
std::list<YHRTSPClient*>::iterator iter;
for (iter = m_listRTSPClient.begin(); iter != m_listRTSPClient.end(); ++iter)
{
if (pClient == (*iter)->pClient)
{
return *iter;
}
else
continue;
}
return NULL;
}

void CYHMediaClient::EraseYHRTSPClient(RTSPClient *pClient)
{
if (m_listRTSPClient.size() == 0)
{
return ;
}
std::list<YHRTSPClient*>::iterator iter;
for (iter = m_listRTSPClient.begin(); iter != m_listRTSPClient.end(); ++iter)
{
if (pClient == (*iter)->pClient)
{
break;
}
else
continue;
}
m_listRTSPClient.erase(iter);
}
LONG CYHMediaClient::GetRTSPClientID(RTSPClient* pClient)
{
std::map<int, RTSPClient*>::iterator iter = m_mapClientID.begin();
int nClientID = -1;
for (; iter != m_mapClientID.end(); ++iter)
{
if (pClient == iter->second)
{
nClientID = iter->first;
}
}
return nClientID;
}

void CYHMediaClient::SetFileSinkAndSocket(YHRTSPClient *pYHClient,unsigned fileSinkBufferSize,unsigned socketInputBufferSize)
{
if (NULL == pYHClient)
{
return;
}
pYHClient->fileSinkBufferSize = fileSinkBufferSize;
pYHClient->socketInputBufferSize = socketInputBufferSize;

return;
}



 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐