xref: /haiku/src/add-ons/media/plugins/rtsp_streamer/RTSPMediaIO.cpp (revision 218a8c03cbadd95d8888b218930f514fa0b4fac4)
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