rtsp_streamer run loop in a separate thread

* Other general improvements.
* Clarify the exit policy.
* Call NotifyError in shutdownStream.
This commit is contained in:
Dario Casalinuovo
2016-06-04 15:51:50 +02:00
parent d004f81304
commit 0957c8215e
3 changed files with 93 additions and 33 deletions
@@ -16,31 +16,46 @@ RTSPMediaIO::RTSPMediaIO(BUrl* ourUrl)
B_MEDIA_STREAMING | B_MEDIA_MUTABLE_SIZE | B_MEDIA_SEEK_BACKWARD, B_MEDIA_STREAMING | B_MEDIA_MUTABLE_SIZE | B_MEDIA_SEEK_BACKWARD,
B_INFINITE_TIMEOUT), B_INFINITE_TIMEOUT),
fUrl(ourUrl), fUrl(ourUrl),
fInitErr(B_OK), fClient(NULL),
fInputAdapter(NULL),
fScheduler(NULL), fScheduler(NULL),
fEnv(NULL), fLoopWatchVariable(0),
loopWatchVariable(0) fLoopThread(-1),
fInitErr(B_OK)
{ {
fInputAdapter = BuildInputAdapter();
fScheduler = BasicTaskScheduler::createNew(); fScheduler = BasicTaskScheduler::createNew();
fEnv = BasicUsageEnvironment::createNew(*fScheduler); fEnv = BasicUsageEnvironment::createNew(*fScheduler);
HaikuRTSPClient* client = new HaikuRTSPClient(*fEnv, fUrl->UrlString(), fClient = new HaikuRTSPClient(*fEnv, fUrl->UrlString(),
0, BuildInputAdapter()); 0, this);
if (client == NULL) { if (fClient == NULL) {
fInitErr = B_ERROR; fInitErr = B_ERROR;
return; return;
} }
client->sendDescribeCommand(continueAfterDESCRIBE); fClient->sendDescribeCommand(continueAfterDESCRIBE);
fEnv->taskScheduler().doEventLoop(&loopWatchVariable); fLoopThread = spawn_thread(_LoopThread, "two minutes hate thread",
B_NORMAL_PRIORITY, this);
fInitErr = client->WaitForInit(5000000); if (fLoopThread <= 0 || resume_thread(fLoopThread) != B_OK) {
fInitErr = B_ERROR;
return;
}
fInitErr = fClient->WaitForInit(5000000);
} }
RTSPMediaIO::~RTSPMediaIO() RTSPMediaIO::~RTSPMediaIO()
{ {
fClient->Close();
ShutdownLoop();
if (fLoopThread != -1)
exit_thread(fLoopThread);
} }
@@ -51,6 +66,13 @@ RTSPMediaIO::InitCheck() const
} }
void
RTSPMediaIO::ShutdownLoop()
{
fLoopWatchVariable = 1;
}
ssize_t ssize_t
RTSPMediaIO::WriteAt(off_t position, const void* buffer, size_t size) RTSPMediaIO::WriteAt(off_t position, const void* buffer, size_t size)
{ {
@@ -58,8 +80,24 @@ RTSPMediaIO::WriteAt(off_t position, const void* buffer, size_t size)
} }
int32
RTSPMediaIO::_LoopThread(void* data)
{
static_cast<RTSPMediaIO *>(data)->LoopThread();
return 0;
}
void
RTSPMediaIO::LoopThread()
{
fEnv->taskScheduler().doEventLoop(&fLoopWatchVariable);
fLoopThread = -1;
}
HaikuRTSPClient::HaikuRTSPClient(UsageEnvironment& env, char const* rtspURL, HaikuRTSPClient::HaikuRTSPClient(UsageEnvironment& env, char const* rtspURL,
portNumBits tunnelOverHTTPPortNum, BInputAdapter* inputAdapter) portNumBits tunnelOverHTTPPortNum, RTSPMediaIO* interface)
: :
RTSPClient(env, rtspURL, LIVE555_VERBOSITY, "Haiku RTSP Streamer", RTSPClient(env, rtspURL, LIVE555_VERBOSITY, "Haiku RTSP Streamer",
tunnelOverHTTPPortNum, -1), tunnelOverHTTPPortNum, -1),
@@ -68,12 +106,30 @@ HaikuRTSPClient::HaikuRTSPClient(UsageEnvironment& env, char const* rtspURL,
subsession(NULL), subsession(NULL),
streamTimerTask(NULL), streamTimerTask(NULL),
duration(0.0f), duration(0.0f),
fInputAdapter(inputAdapter) fInterface(interface),
fInitPort(-1)
{ {
fInitPort = create_port(1, "RTSP Client wait port"); fInitPort = create_port(1, "RTSP Client wait port");
} }
HaikuRTSPClient::~HaikuRTSPClient()
{
}
void
HaikuRTSPClient::Close()
{
delete iter;
if (session != NULL) {
UsageEnvironment& env = session->envir();
env.taskScheduler().unscheduleDelayedTask(streamTimerTask);
Medium::close(session);
}
}
status_t status_t
HaikuRTSPClient::WaitForInit(bigtime_t timeout) HaikuRTSPClient::WaitForInit(bigtime_t timeout)
{ {
@@ -90,6 +146,7 @@ HaikuRTSPClient::WaitForInit(bigtime_t timeout)
void void
HaikuRTSPClient::NotifyError() HaikuRTSPClient::NotifyError()
{ {
fInterface->ShutdownLoop();
status_t status = B_ERROR; status_t status = B_ERROR;
write_port(fInitPort, NULL, &status, sizeof(status)); write_port(fInitPort, NULL, &status, sizeof(status));
} }
@@ -103,19 +160,8 @@ HaikuRTSPClient::NotifySucces()
} }
HaikuRTSPClient::~HaikuRTSPClient()
{
delete iter;
if (session != NULL) {
UsageEnvironment& env = session->envir();
env.taskScheduler().unscheduleDelayedTask(streamTimerTask);
Medium::close(session);
}
}
BInputAdapter* BInputAdapter*
HaikuRTSPClient::GetInputAdapter() const HaikuRTSPClient::GetInputAdapter() const
{ {
return fInputAdapter; return fInterface->BuildInputAdapter();
} }
@@ -12,6 +12,9 @@
#include "rtsp.h" #include "rtsp.h"
class HaikuRTSPClient;
class RTSPMediaIO : public BAdapterIO class RTSPMediaIO : public BAdapterIO
{ {
public: public:
@@ -23,12 +26,22 @@ public:
virtual ssize_t WriteAt(off_t position, virtual ssize_t WriteAt(off_t position,
const void* buffer, const void* buffer,
size_t size); size_t size);
private:
BUrl* fUrl;
TaskScheduler* fScheduler; void LoopThread();
void ShutdownLoop();
private:
static int32 _LoopThread(void* data);
BUrl* fUrl;
BInputAdapter* fInputAdapter;
HaikuRTSPClient* fClient;
UsageEnvironment* fEnv; UsageEnvironment* fEnv;
char loopWatchVariable; TaskScheduler* fScheduler;
char fLoopWatchVariable;
thread_id fLoopThread;
status_t fInitErr; status_t fInitErr;
}; };
@@ -40,7 +53,9 @@ public:
HaikuRTSPClient(UsageEnvironment& env, HaikuRTSPClient(UsageEnvironment& env,
char const* rtspURL, char const* rtspURL,
portNumBits tunnelOverHTTPPortNum, portNumBits tunnelOverHTTPPortNum,
BInputAdapter* fInputAdapter); RTSPMediaIO* fInputAdapter);
void Close();
BInputAdapter* GetInputAdapter() const; BInputAdapter* GetInputAdapter() const;
@@ -50,10 +65,9 @@ public:
void NotifySucces(); void NotifySucces();
protected: protected:
virtual ~HaikuRTSPClient(); virtual ~HaikuRTSPClient();
public: public:
MediaSubsessionIterator* iter; MediaSubsessionIterator* iter;
MediaSession* session; MediaSession* session;
MediaSubsession* subsession; MediaSubsession* subsession;
@@ -61,7 +75,8 @@ public:
double duration; double duration;
private: private:
BInputAdapter* fInputAdapter; RTSPMediaIO* fInterface;
port_id fInitPort; port_id fInitPort;
}; };
@@ -125,7 +125,6 @@ void continueAfterDESCRIBE(RTSPClient* rtspClient,
return; return;
} while (0); } while (0);
client->NotifyError();
// An unrecoverable error occurred with this stream. // An unrecoverable error occurred with this stream.
shutdownStream(rtspClient); shutdownStream(rtspClient);
} }
@@ -289,7 +288,6 @@ void continueAfterPLAY(RTSPClient* rtspClient,
delete[] resultString; delete[] resultString;
if (!success) { if (!success) {
client->NotifyError();
// An unrecoverable error occurred with this stream. // An unrecoverable error occurred with this stream.
shutdownStream(rtspClient); shutdownStream(rtspClient);
} else } else
@@ -383,6 +381,7 @@ void shutdownStream(RTSPClient* rtspClient, int exitCode)
Medium::close(rtspClient); Medium::close(rtspClient);
// Note that this will also cause this stream's // Note that this will also cause this stream's
// "StreamClientState" structure to get reclaimed. // "StreamClientState" structure to get reclaimed.
client->NotifyError();
} }