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