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 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 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 42 RTSPMediaIO::WriteAt(off_t position, const void* buffer, size_t size) 43 { 44 return B_NOT_SUPPORTED; 45 } 46 47 48 status_t 49 RTSPMediaIO::SetSize(off_t size) 50 { 51 return B_NOT_SUPPORTED; 52 } 53 54 55 status_t 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 76 RTSPMediaIO::_LoopThread(void* data) 77 { 78 static_cast<RTSPMediaIO *>(data)->LoopThread(); 79 return 0; 80 } 81 82 83 void 84 RTSPMediaIO::LoopThread() 85 { 86 fEnv->taskScheduler().doEventLoop(&fLoopWatchVariable); 87 fLoopThread = -1; 88 } 89 90 91 void 92 RTSPMediaIO::ShutdownLoop() 93 { 94 fLoopWatchVariable = 1; 95 } 96 97 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 115 HaikuRTSPClient::~HaikuRTSPClient() 116 { 117 } 118 119 120 void 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 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 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 158 HaikuRTSPClient::NotifySucces() 159 { 160 status_t status = B_OK; 161 write_port(fInitPort, NULL, &status, sizeof(status)); 162 } 163 164 165 BInputAdapter* 166 HaikuRTSPClient::GetInputAdapter() const 167 { 168 return fInterface->BuildInputAdapter(); 169 } 170