1 /*
2 * Copyright 2003-2021 The Music Player Daemon Project
3 * http://www.musicpd.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "OpusEncoderPlugin.hxx"
21 #include "OggEncoder.hxx"
22 #include "pcm/AudioFormat.hxx"
23 #include "util/ByteOrder.hxx"
24 #include "util/StringUtil.hxx"
25
26 #include <opus.h>
27 #include <ogg/ogg.h>
28
29 #include <cassert>
30 #include <stdexcept>
31
32 #include <stdlib.h>
33
34 namespace {
35
36 class OpusEncoder final : public OggEncoder {
37 const AudioFormat audio_format;
38
39 const size_t frame_size;
40
41 const size_t buffer_frames, buffer_size;
42 size_t buffer_position = 0;
43 uint8_t *const buffer;
44
45 ::OpusEncoder *const enc;
46
47 unsigned char buffer2[1275 * 3 + 7];
48
49 int lookahead;
50
51 ogg_int64_t packetno = 0;
52
53 ogg_int64_t granulepos = 0;
54
55 public:
56 OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc, bool _chaining);
57 ~OpusEncoder() noexcept override;
58
59 OpusEncoder(const OpusEncoder &) = delete;
60 OpusEncoder &operator=(const OpusEncoder &) = delete;
61
62 /* virtual methods from class Encoder */
63 void End() override;
64 void Write(const void *data, size_t length) override;
65
66 void PreTag() override;
67 void SendTag(const Tag &tag) override;
68
69 private:
70 void DoEncode(bool eos);
71 void WriteSilence(unsigned fill_frames);
72
73 void GenerateHeaders(const Tag *tag) noexcept;
74 void GenerateHead() noexcept;
75 void GenerateTags(const Tag *tag) noexcept;
76 };
77
78 class PreparedOpusEncoder final : public PreparedEncoder {
79 opus_int32 bitrate;
80 int complexity;
81 int signal;
82 int packet_loss;
83 int vbr;
84 int vbr_constraint;
85 const bool chaining;
86
87 public:
88 explicit PreparedOpusEncoder(const ConfigBlock &block);
89
90 /* virtual methods from class PreparedEncoder */
91 Encoder *Open(AudioFormat &audio_format) override;
92
GetMimeType() const93 [[nodiscard]] const char *GetMimeType() const noexcept override {
94 return "audio/ogg";
95 }
96 };
97
PreparedOpusEncoder(const ConfigBlock & block)98 PreparedOpusEncoder::PreparedOpusEncoder(const ConfigBlock &block)
99 :chaining(block.GetBlockValue("opustags", false))
100 {
101 const char *value = block.GetBlockValue("bitrate", "auto");
102 if (strcmp(value, "auto") == 0)
103 bitrate = OPUS_AUTO;
104 else if (strcmp(value, "max") == 0)
105 bitrate = OPUS_BITRATE_MAX;
106 else {
107 char *endptr;
108 bitrate = strtoul(value, &endptr, 10);
109 if (endptr == value || *endptr != 0 ||
110 bitrate < 500 || bitrate > 512000)
111 throw std::runtime_error("Invalid bit rate");
112 }
113
114 complexity = block.GetBlockValue("complexity", 10U);
115 if (complexity > 10)
116 throw std::runtime_error("Invalid complexity");
117
118 value = block.GetBlockValue("signal", "auto");
119 if (strcmp(value, "auto") == 0)
120 signal = OPUS_AUTO;
121 else if (strcmp(value, "voice") == 0)
122 signal = OPUS_SIGNAL_VOICE;
123 else if (strcmp(value, "music") == 0)
124 signal = OPUS_SIGNAL_MUSIC;
125 else
126 throw std::runtime_error("Invalid signal");
127
128 value = block.GetBlockValue("vbr", "yes");
129 if (strcmp(value, "yes") == 0) {
130 vbr = 1U;
131 vbr_constraint = 0U;
132 } else if (strcmp(value, "no") == 0) {
133 vbr = 0U;
134 vbr_constraint = 0U;
135 } else if (strcmp(value, "constrained") == 0) {
136 vbr = 1U;
137 vbr_constraint = 1U;
138 } else
139 throw std::runtime_error("Invalid vbr");
140
141 packet_loss = block.GetBlockValue("packet_loss", 0U);
142 if (packet_loss > 100)
143 throw std::runtime_error("Invalid packet loss");
144 }
145
146 PreparedEncoder *
opus_encoder_init(const ConfigBlock & block)147 opus_encoder_init(const ConfigBlock &block)
148 {
149 return new PreparedOpusEncoder(block);
150 }
151
OpusEncoder(AudioFormat & _audio_format,::OpusEncoder * _enc,bool _chaining)152 OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc, bool _chaining)
153 :OggEncoder(_chaining),
154 audio_format(_audio_format),
155 frame_size(_audio_format.GetFrameSize()),
156 buffer_frames(_audio_format.sample_rate / 50),
157 buffer_size(frame_size * buffer_frames),
158 buffer(new uint8_t[buffer_size]),
159 enc(_enc)
160 {
161 opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&lookahead));
162 GenerateHeaders(nullptr);
163 }
164
165 Encoder *
Open(AudioFormat & audio_format)166 PreparedOpusEncoder::Open(AudioFormat &audio_format)
167 {
168 /* libopus supports only 48 kHz */
169 audio_format.sample_rate = 48000;
170
171 if (audio_format.channels > 2)
172 audio_format.channels = 1;
173
174 switch (audio_format.format) {
175 case SampleFormat::S16:
176 case SampleFormat::FLOAT:
177 break;
178
179 case SampleFormat::S8:
180 audio_format.format = SampleFormat::S16;
181 break;
182
183 default:
184 audio_format.format = SampleFormat::FLOAT;
185 break;
186 }
187
188 int error_code;
189 auto *enc = opus_encoder_create(audio_format.sample_rate,
190 audio_format.channels,
191 OPUS_APPLICATION_AUDIO,
192 &error_code);
193 if (enc == nullptr)
194 throw std::runtime_error(opus_strerror(error_code));
195
196 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
197 opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
198 opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal));
199 opus_encoder_ctl(enc, OPUS_SET_VBR(vbr));
200 opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(vbr_constraint));
201 opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss));
202
203 return new OpusEncoder(audio_format, enc, chaining);
204 }
205
~OpusEncoder()206 OpusEncoder::~OpusEncoder() noexcept
207 {
208 delete[] buffer;
209 opus_encoder_destroy(enc);
210 }
211
212 void
DoEncode(bool eos)213 OpusEncoder::DoEncode(bool eos)
214 {
215 assert(buffer_position == buffer_size || eos);
216
217 opus_int32 result =
218 audio_format.format == SampleFormat::S16
219 ? opus_encode(enc,
220 (const opus_int16 *)buffer,
221 buffer_frames,
222 buffer2,
223 sizeof(buffer2))
224 : opus_encode_float(enc,
225 (const float *)buffer,
226 buffer_frames,
227 buffer2,
228 sizeof(buffer2));
229 if (result < 0)
230 throw std::runtime_error("Opus encoder error");
231
232 granulepos += buffer_position / frame_size;
233
234 ogg_packet packet;
235 packet.packet = buffer2;
236 packet.bytes = result;
237 packet.b_o_s = false;
238 packet.e_o_s = eos;
239 packet.granulepos = granulepos;
240 packet.packetno = packetno++;
241 stream.PacketIn(packet);
242
243 buffer_position = 0;
244 }
245
246 void
End()247 OpusEncoder::End()
248 {
249 memset(buffer + buffer_position, 0,
250 buffer_size - buffer_position);
251 DoEncode(true);
252 Flush();
253 }
254
255 void
WriteSilence(unsigned fill_frames)256 OpusEncoder::WriteSilence(unsigned fill_frames)
257 {
258 size_t fill_bytes = fill_frames * frame_size;
259
260 while (fill_bytes > 0) {
261 size_t nbytes = buffer_size - buffer_position;
262 if (nbytes > fill_bytes)
263 nbytes = fill_bytes;
264
265 memset(buffer + buffer_position, 0, nbytes);
266 buffer_position += nbytes;
267 fill_bytes -= nbytes;
268
269 if (buffer_position == buffer_size)
270 DoEncode(false);
271 }
272 }
273
274 void
Write(const void * _data,size_t length)275 OpusEncoder::Write(const void *_data, size_t length)
276 {
277 const auto *data = (const uint8_t *)_data;
278
279 if (lookahead > 0) {
280 /* generate some silence at the beginning of the
281 stream */
282
283 assert(buffer_position == 0);
284
285 WriteSilence(lookahead);
286 lookahead = 0;
287 }
288
289 while (length > 0) {
290 size_t nbytes = buffer_size - buffer_position;
291 if (nbytes > length)
292 nbytes = length;
293
294 memcpy(buffer + buffer_position, data, nbytes);
295 data += nbytes;
296 length -= nbytes;
297 buffer_position += nbytes;
298
299 if (buffer_position == buffer_size)
300 DoEncode(false);
301 }
302 }
303
304 void
GenerateHeaders(const Tag * tag)305 OpusEncoder::GenerateHeaders(const Tag *tag) noexcept
306 {
307 GenerateHead();
308 GenerateTags(tag);
309 }
310
311 void
GenerateHead()312 OpusEncoder::GenerateHead() noexcept
313 {
314 unsigned char header[19];
315 memcpy(header, "OpusHead", 8);
316 header[8] = 1;
317 header[9] = audio_format.channels;
318 *(uint16_t *)(header + 10) = ToLE16(lookahead);
319 *(uint32_t *)(header + 12) = ToLE32(audio_format.sample_rate);
320 header[16] = 0;
321 header[17] = 0;
322 header[18] = 0;
323
324 ogg_packet packet;
325 packet.packet = header;
326 packet.bytes = sizeof(header);
327 packet.b_o_s = true;
328 packet.e_o_s = false;
329 packet.granulepos = 0;
330 packet.packetno = packetno++;
331 stream.PacketIn(packet);
332 // flush not needed because libogg autoflushes on b_o_s flag
333 }
334
335 void
GenerateTags(const Tag * tag)336 OpusEncoder::GenerateTags(const Tag *tag) noexcept
337 {
338 const char *version = opus_get_version_string();
339 size_t version_length = strlen(version);
340
341 // len("OpusTags") + 4 byte version length + len(version) + 4 byte tag count
342 size_t comments_size = 8 + 4 + version_length + 4;
343 uint32_t tag_count = 0;
344 if (tag) {
345 for (const auto &item: *tag) {
346 ++tag_count;
347 // 4 byte length + len(tagname) + len('=') + len(value)
348 comments_size += 4 + strlen(tag_item_names[item.type]) + 1 + strlen(item.value);
349 }
350 }
351
352 auto *comments = new unsigned char[comments_size];
353 unsigned char *p = comments;
354
355 memcpy(comments, "OpusTags", 8);
356 *(uint32_t *)(comments + 8) = ToLE32(version_length);
357 p += 12;
358
359 memcpy(p, version, version_length);
360 p += version_length;
361
362 tag_count = ToLE32(tag_count);
363 memcpy(p, &tag_count, 4);
364 p += 4;
365
366 if (tag) {
367 for (const auto &item: *tag) {
368 size_t tag_name_len = strlen(tag_item_names[item.type]);
369 size_t tag_val_len = strlen(item.value);
370 uint32_t tag_len_le = ToLE32(tag_name_len + 1 + tag_val_len);
371
372 memcpy(p, &tag_len_le, 4);
373 p += 4;
374
375 ToUpperASCII((char *)p, tag_item_names[item.type], tag_name_len + 1);
376 p += tag_name_len;
377
378 *p++ = '=';
379
380 memcpy(p, item.value, tag_val_len);
381 p += tag_val_len;
382 }
383 }
384 assert(comments + comments_size == p);
385
386 ogg_packet packet;
387 packet.packet = comments;
388 packet.bytes = comments_size;
389 packet.b_o_s = false;
390 packet.e_o_s = false;
391 packet.granulepos = 0;
392 packet.packetno = packetno++;
393 stream.PacketIn(packet);
394 Flush();
395
396 delete[] comments;
397 }
398
399 void
PreTag()400 OpusEncoder::PreTag()
401 {
402 End();
403 packetno = 0;
404 granulepos = 0; // not really required, but useful to prevent wraparound
405 opus_encoder_ctl(enc, OPUS_RESET_STATE);
406 }
407
408 void
SendTag(const Tag & tag)409 OpusEncoder::SendTag(const Tag &tag)
410 {
411 stream.Reinitialize(GenerateSerial());
412 opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&lookahead));
413 GenerateHeaders(&tag);
414 }
415
416 } // namespace
417
418 const EncoderPlugin opus_encoder_plugin = {
419 "opus",
420 opus_encoder_init,
421 };
422