1 /*
2 * Copyright 2016, Dario Casalinuovo. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "RTSPMediaIO.h"
8
9
10 #define LIVE555_VERBOSITY 1
11
12
RTSPMediaIO(BUrl ourUrl)13 RTSPMediaIO::RTSPMediaIO(BUrl ourUrl)
14 :
15 BAdapterIO(
16 B_MEDIA_STREAMING | B_MEDIA_MUTABLE_SIZE | B_MEDIA_SEEK_BACKWARD,
17 B_INFINITE_TIMEOUT),
18 fUrl(ourUrl),
19 fClient(NULL),
20 fScheduler(NULL),
21 fLoopWatchVariable(0),
22 fLoopThread(-1)
23 {
24 fScheduler = BasicTaskScheduler::createNew();
25 fEnv = BasicUsageEnvironment::createNew(*fScheduler);
26 }
27
28
~RTSPMediaIO()29 RTSPMediaIO::~RTSPMediaIO()
30 {
31 fClient->Close();
32
33 ShutdownLoop();
34
35 status_t status;
36 if (fLoopThread != -1)
37 wait_for_thread(fLoopThread, &status);
38 }
39
40
41 ssize_t
WriteAt(off_t position,const void * buffer,size_t size)42 RTSPMediaIO::WriteAt(off_t position, const void* buffer, size_t size)
43 {
44 return B_NOT_SUPPORTED;
45 }
46
47
48 status_t
SetSize(off_t size)49 RTSPMediaIO::SetSize(off_t size)
50 {
51 return B_NOT_SUPPORTED;
52 }
53
54
55 status_t
Open()56 RTSPMediaIO::Open()
57 {
58 fClient = new HaikuRTSPClient(*fEnv, fUrl.UrlString(),
59 0, this);
60 if (fClient == NULL)
61 return B_ERROR;
62
63 fClient->sendDescribeCommand(continueAfterDESCRIBE);
64
65 fLoopThread = spawn_thread(_LoopThread, "two minutes hate thread",
66 B_NORMAL_PRIORITY, this);
67
68 if (fLoopThread <= 0 || resume_thread(fLoopThread) != B_OK)
69 return B_ERROR;
70
71 return fClient->WaitForInit(5000000);
72 }
73
74
75 int32
_LoopThread(void * data)76 RTSPMediaIO::_LoopThread(void* data)
77 {
78 static_cast<RTSPMediaIO *>(data)->LoopThread();
79 return 0;
80 }
81
82
83 void
LoopThread()84 RTSPMediaIO::LoopThread()
85 {
86 fEnv->taskScheduler().doEventLoop(&fLoopWatchVariable);
87 fLoopThread = -1;
88 }
89
90
91 void
ShutdownLoop()92 RTSPMediaIO::ShutdownLoop()
93 {
94 fLoopWatchVariable = 1;
95 }
96
97
HaikuRTSPClient(UsageEnvironment & env,char const * rtspURL,portNumBits tunnelOverHTTPPortNum,RTSPMediaIO * interface)98 HaikuRTSPClient::HaikuRTSPClient(UsageEnvironment& env, char const* rtspURL,
99 portNumBits tunnelOverHTTPPortNum, RTSPMediaIO* interface)
100 :
101 RTSPClient(env, rtspURL, LIVE555_VERBOSITY, "Haiku RTSP Streamer",
102 tunnelOverHTTPPortNum, -1),
103 iter(NULL),
104 session(NULL),
105 subsession(NULL),
106 streamTimerTask(NULL),
107 duration(0.0f),
108 fInterface(interface),
109 fInitPort(-1)
110 {
111 fInitPort = create_port(1, "RTSP Client wait port");
112 }
113
114
~HaikuRTSPClient()115 HaikuRTSPClient::~HaikuRTSPClient()
116 {
117 }
118
119
120 void
Close()121 HaikuRTSPClient::Close()
122 {
123 delete iter;
124 if (session != NULL) {
125 UsageEnvironment& env = session->envir();
126 env.taskScheduler().unscheduleDelayedTask(streamTimerTask);
127 Medium::close(session);
128 }
129 }
130
131
132 status_t
WaitForInit(bigtime_t timeout)133 HaikuRTSPClient::WaitForInit(bigtime_t timeout)
134 {
135 status_t status = B_ERROR;
136 if (read_port_etc(fInitPort, NULL, &status,
137 sizeof(status), B_RELATIVE_TIMEOUT, timeout) < 0) {
138 return B_ERROR;
139 }
140
141 close_port(fInitPort);
142 delete_port(fInitPort);
143 fInitPort = -1;
144 return status;
145 }
146
147
148 void
NotifyError()149 HaikuRTSPClient::NotifyError()
150 {
151 fInterface->ShutdownLoop();
152 status_t status = B_ERROR;
153 write_port(fInitPort, NULL, &status, sizeof(status));
154 }
155
156
157 void
NotifySucces()158 HaikuRTSPClient::NotifySucces()
159 {
160 status_t status = B_OK;
161 write_port(fInitPort, NULL, &status, sizeof(status));
162 }
163
164
165 BInputAdapter*
GetInputAdapter() const166 HaikuRTSPClient::GetInputAdapter() const
167 {
168 return fInterface->BuildInputAdapter();
169 }
170