1 /*
2 * Copyright (C) 2020
3 * Matthias P. Braendli (matthias.braendli@mpb.li)
4 *
5 * This file is part of the welle.io.
6 * Many of the ideas as implemented in welle.io are derived from
7 * other work, made available through the GNU general Public License.
8 * All copyrights of the original authors are recognized.
9 *
10 * welle.io is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * welle.io is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with welle.io; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25 #include "webprogrammehandler.h"
26 #include <iostream>
27 #include <algorithm>
28
29 using namespace std;
30
31 #ifndef MSG_NOSIGNAL
32 #define MSG_NOSIGNAL 0
33 #endif
34
ProgrammeSender(Socket && s)35 ProgrammeSender::ProgrammeSender(Socket&& s) :
36 s(move(s))
37 {
38 }
39
ProgrammeSender(ProgrammeSender && other)40 ProgrammeSender::ProgrammeSender(ProgrammeSender&& other) :
41 s(move(other.s))
42 {
43 }
44
operator =(ProgrammeSender && other)45 ProgrammeSender& ProgrammeSender::operator=(ProgrammeSender&& other)
46 {
47 s = move(other.s);
48 other.running = false;
49 return *this;
50 }
51
send_mp3(const std::vector<uint8_t> & mp3Data)52 bool ProgrammeSender::send_mp3(const std::vector<uint8_t>& mp3Data)
53 {
54 if (not s.valid()) {
55 return false;
56 }
57
58 const int flags = MSG_NOSIGNAL;
59
60 ssize_t ret = s.send(mp3Data.data(), mp3Data.size(), flags);
61 if (ret == -1) {
62 s.close();
63 std::unique_lock<std::mutex> lock(mutex);
64 running = false;
65 lock.unlock();
66 cv.notify_all();
67 return false;
68 }
69
70 return true;
71 }
72
wait_for_termination() const73 void ProgrammeSender::wait_for_termination() const
74 {
75 std::unique_lock<std::mutex> lock(mutex);
76 while (running) {
77 cv.wait_for(lock, chrono::seconds(2));
78 }
79 }
80
cancel()81 void ProgrammeSender::cancel()
82 {
83 s.close();
84 running = false;
85 }
86
WebProgrammeHandler(uint32_t serviceId)87 WebProgrammeHandler::WebProgrammeHandler(uint32_t serviceId) :
88 serviceId(serviceId)
89 {
90 const auto now = chrono::system_clock::now();
91 time_label = now;
92 time_label_change = now;
93 time_mot = now;
94 time_mot_change = now;
95 }
96
WebProgrammeHandler(WebProgrammeHandler && other)97 WebProgrammeHandler::WebProgrammeHandler(WebProgrammeHandler&& other) :
98 serviceId(other.serviceId),
99 senders(move(other.senders))
100 {
101 other.senders.clear();
102 other.serviceId = 0;
103
104 const auto now = chrono::system_clock::now();
105 time_label = now;
106 time_label_change = now;
107 time_mot = now;
108 time_mot_change = now;
109 }
110
registerSender(ProgrammeSender * sender)111 void WebProgrammeHandler::registerSender(ProgrammeSender *sender)
112 {
113 std::unique_lock<std::mutex> lock(senders_mutex);
114 senders.push_back(sender);
115 }
116
removeSender(ProgrammeSender * sender)117 void WebProgrammeHandler::removeSender(ProgrammeSender *sender)
118 {
119 std::unique_lock<std::mutex> lock(senders_mutex);
120 senders.remove(sender);
121 }
122
needsToBeDecoded() const123 bool WebProgrammeHandler::needsToBeDecoded() const
124 {
125 std::unique_lock<std::mutex> lock(senders_mutex);
126 return not senders.empty();
127 }
128
cancelAll()129 void WebProgrammeHandler::cancelAll()
130 {
131 std::unique_lock<std::mutex> lock(senders_mutex);
132 for (auto& s : senders) {
133 s->cancel();
134 }
135 }
136
getDLS() const137 WebProgrammeHandler::dls_t WebProgrammeHandler::getDLS() const
138 {
139 dls_t dls;
140
141 std::unique_lock<std::mutex> lock(stats_mutex);
142 if (last_label_valid) {
143 dls.label = last_label;
144 dls.time = time_label;
145 dls.last_changed = time_label_change;
146 }
147
148 return dls;
149 }
150
getMOT() const151 WebProgrammeHandler::mot_t WebProgrammeHandler::getMOT() const
152 {
153 mot_t mot;
154
155 std::unique_lock<std::mutex> lock(stats_mutex);
156 if (last_mot_valid) {
157 mot.data = last_mot;
158 mot.time = time_mot;
159 mot.last_changed = time_mot_change;
160 mot.subtype = last_subtype;
161 }
162 return mot;
163 }
164
getXPADErrors() const165 WebProgrammeHandler::xpad_error_t WebProgrammeHandler::getXPADErrors() const
166 {
167 std::unique_lock<std::mutex> lock(stats_mutex);
168 xpad_error_t r(xpad_error);
169 return r;
170 }
171
getAudioLevels() const172 WebProgrammeHandler::audiolevels_t WebProgrammeHandler::getAudioLevels() const
173 {
174 std::unique_lock<std::mutex> lock(stats_mutex);
175 audiolevels_t r(audiolevels);
176 return r;
177 }
178
getErrorCounters() const179 WebProgrammeHandler::errorcounters_t WebProgrammeHandler::getErrorCounters() const
180 {
181 std::unique_lock<std::mutex> lock(stats_mutex);
182 errorcounters_t r(errorcounters);
183 return r;
184 }
185
onFrameErrors(int frameErrors)186 void WebProgrammeHandler::onFrameErrors(int frameErrors)
187 {
188 std::unique_lock<std::mutex> lock(stats_mutex);
189 errorcounters.num_frameErrors += frameErrors;
190 errorcounters.time = chrono::system_clock::now();
191 }
192
onNewAudio(std::vector<int16_t> && audioData,int sampleRate,const string & m)193 void WebProgrammeHandler::onNewAudio(std::vector<int16_t>&& audioData,
194 int sampleRate, const string& m)
195 {
196 rate = sampleRate;
197 mode = m;
198
199 if (audioData.empty()) {
200 return;
201 }
202
203 // The audio decoders always upconvert to stereo
204 const int channels = 2;
205
206 int last_audioLevel_L = 0;
207 int last_audioLevel_R = 0;
208 {
209 int16_t max_L = 0;
210 int16_t max_R = 0;
211 for (size_t i = 0; i < audioData.size()-1; i+=2) {
212 max_L = std::max(max_L, audioData[i]);
213 max_R = std::max(max_R, audioData[i+1]);
214 }
215 last_audioLevel_L = max_L;
216 last_audioLevel_R = max_R;
217 }
218
219 {
220 std::unique_lock<std::mutex> lock(stats_mutex);
221 audiolevels.time = chrono::system_clock::now();
222 audiolevels.last_audioLevel_L = last_audioLevel_L;
223 audiolevels.last_audioLevel_R = last_audioLevel_R;
224 }
225
226 if (not lame_initialised) {
227 lame_set_in_samplerate(lame.lame, rate);
228 lame_set_num_channels(lame.lame, channels);
229 lame_set_VBR(lame.lame, vbr_default);
230 lame_set_VBR_q(lame.lame, 2);
231 lame_init_params(lame.lame);
232 lame_initialised = true;
233 }
234
235 vector<uint8_t> mp3buf(16384);
236
237 int written = lame_encode_buffer_interleaved(lame.lame,
238 audioData.data(), audioData.size()/channels,
239 mp3buf.data(), mp3buf.size());
240
241 if (written < 0) {
242 cerr << "Failed to encode mp3: " << written << endl;
243 }
244 else if (written > (ssize_t)mp3buf.size()) {
245 cerr << "mp3 encoder wrote more than buffer size!" << endl;
246 }
247 else if (written > 0) {
248 mp3buf.resize(written);
249
250 std::unique_lock<std::mutex> lock(senders_mutex);
251
252 for (auto& s : senders) {
253 bool success = s->send_mp3(mp3buf);
254 if (not success) {
255 cerr << "Failed to send audio for " << serviceId << endl;
256 }
257 }
258 }
259 }
260
onRsErrors(bool uncorrectedErrors,int numCorrectedErrors)261 void WebProgrammeHandler::onRsErrors(bool uncorrectedErrors, int numCorrectedErrors)
262 {
263 (void)numCorrectedErrors; // TODO calculate BER before Reed-Solomon
264 std::unique_lock<std::mutex> lock(stats_mutex);
265 errorcounters.num_rsErrors += (uncorrectedErrors ? 1 : 0);
266 errorcounters.time = chrono::system_clock::now();
267 }
268
onAacErrors(int aacErrors)269 void WebProgrammeHandler::onAacErrors(int aacErrors)
270 {
271 std::unique_lock<std::mutex> lock(stats_mutex);
272 errorcounters.num_aacErrors += aacErrors;
273 errorcounters.time = chrono::system_clock::now();
274 }
275
onNewDynamicLabel(const string & label)276 void WebProgrammeHandler::onNewDynamicLabel(const string& label)
277 {
278 std::unique_lock<std::mutex> lock(stats_mutex);
279 last_label_valid = true;
280 const auto now = chrono::system_clock::now();
281 time_label = now;
282 if (last_label != label) {
283 time_label_change = now;
284 }
285 last_label = label;
286 }
287
onMOT(const mot_file_t & mot_file)288 void WebProgrammeHandler::onMOT(const mot_file_t& mot_file)
289 {
290 std::unique_lock<std::mutex> lock(stats_mutex);
291 last_mot_valid = true;
292 const auto now = chrono::system_clock::now();
293 time_mot = now;
294 if (last_mot != mot_file.data) {
295 time_mot_change = now;
296 }
297 last_mot = mot_file.data;
298 if (mot_file.content_sub_type == 0x01) {
299 last_subtype = MOTType::JPEG;
300 }
301 else if (mot_file.content_sub_type == 0x03) {
302 last_subtype = MOTType::PNG;
303 }
304 else {
305 last_subtype = MOTType::Unknown;
306 }
307 }
308
onPADLengthError(size_t announced_xpad_len,size_t xpad_len)309 void WebProgrammeHandler::onPADLengthError(size_t announced_xpad_len, size_t xpad_len)
310 {
311 std::unique_lock<std::mutex> lock(stats_mutex);
312 xpad_error.has_error = true;
313 xpad_error.time = chrono::system_clock::now();
314 xpad_error.announced_xpad_len = announced_xpad_len;
315 xpad_error.xpad_len = xpad_len;
316 }
317
318