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