1 /*************************************************************************
2 OpusEncoder.cpp - sub encoder base class for Opus in an Ogg container
3 -------------------
4 begin : Thu Jan 03 2013
5 copyright : (C) 2013 by Thomas Eschenbacher
6 email : Thomas.Eschenbacher@gmx.de
7
8 ***************************************************************************
9 * *
10 * This program 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 ***************************************************************************
16
17 parts based on source snippets taken from "opusenc.c", opus-tools-0.1.5
18 -------------------------------------------------------------------------
19 Copyright (C) 2002-2011 Jean-Marc Valin <jmvalin@jmvalin.ca>
20 Copyright (C) 2007-2012 Xiph.Org Foundation <monty@xiph.org/>
21 Copyright (C) 2008-2012 Gregory Maxwell <greg@xiph.org>
22 File: opusenc.c
23
24 Redistribution and use in source and binary forms, with or without
25 modification, are permitted provided that the following conditions
26 are met:
27
28 - Redistributions of source code must retain the above copyright
29 notice, this list of conditions and the following disclaimer.
30
31 - Redistributions in binary form must reproduce the above copyright
32 notice, this list of conditions and the following disclaimer in the
33 documentation and/or other materials provided with the distribution.
34
35 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
39 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
43 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46
47 ***************************************************************************/
48
49 #include "config.h"
50
51 #include <math.h>
52 #include <string.h>
53 #include <new>
54
55 #include <opus/opus_defines.h>
56
57 #include <QApplication>
58 #include <QBuffer>
59 #include <QByteArray>
60 #include <QList>
61 #include <QRandomGenerator>
62 #include <QString>
63 #include <QTime>
64 #include <QtGlobal>
65 #include <QtEndian>
66
67 #include <KLocalizedString>
68
69 #include "libkwave/BitrateMode.h"
70 #include "libkwave/Connect.h"
71 #include "libkwave/MessageBox.h"
72 #include "libkwave/MultiTrackReader.h"
73 #include "libkwave/Sample.h"
74 #include "libkwave/SampleArray.h"
75 #include "libkwave/Utils.h"
76 #include "libkwave/modules/ChannelMixer.h"
77 #include "libkwave/modules/RateConverter.h"
78
79 #include "OpusCommon.h"
80 #include "OpusEncoder.h"
81
82 /** lowest supported bitrate */
83 #define BITRATE_MIN 500
84
85 /** highest supported bitrate */
86 #define BITRATE_MAX 256000
87
88 /** lowest (reasonable) supported sample rate */
89 #define SAMPLE_RATE_MIN 1000
90
91 /** highest (reasonable) supported sample rate */
92 #define SAMPLE_RATE_MAX 512000
93
94 /** default encoder complexity */
95 #define DEFAULT_COMPLEXITY 10
96
97 /***************************************************************************/
OpusEncoder()98 Kwave::OpusEncoder::OpusEncoder()
99 :m_comments_map(),
100 m_info(),
101 m_downmix(DOWNMIX_AUTO),
102 m_bitrate(0),
103 m_coding_rate(0),
104 m_encoder_channels(0),
105 m_channel_mixer(Q_NULLPTR),
106 m_rate_converter(Q_NULLPTR),
107 m_frame_size(0),
108 m_extra_out(0),
109 m_opus_header(),
110 m_max_frame_bytes(0),
111 m_packet_buffer(Q_NULLPTR),
112 m_encoder(Q_NULLPTR),
113 m_encoder_input(Q_NULLPTR),
114 m_last_queue_element(Q_NULLPTR),
115 m_buffer(Q_NULLPTR)
116 {
117
118 memset(&m_opus_header, 0x00, sizeof(m_opus_header));
119 memset(&m_opus_header.map, 0xFF, sizeof(m_opus_header.map));
120 }
121
122 /***************************************************************************/
~OpusEncoder()123 Kwave::OpusEncoder::~OpusEncoder()
124 {
125 }
126
127 /***************************************************************************/
setupDownMix(QWidget * widget,unsigned int tracks,int bitrate)128 bool Kwave::OpusEncoder::setupDownMix(QWidget *widget, unsigned int tracks,
129 int bitrate)
130 {
131 // get "downmix" setting, default is "auto"
132 m_downmix = DOWNMIX_AUTO; // currently not user configurable
133
134 if ((m_downmix == DOWNMIX_AUTO) &&
135 (bitrate > 0) && (bitrate < (32000 * Kwave::toInt(tracks))))
136 {
137 if (tracks > 8) {
138 // downmix from more than 8 channels to mono
139 if (Kwave::MessageBox::warningContinueCancel(
140 widget,
141 i18n("Surround bitrate would be less than 32kBit/sec per "
142 "channel, this file should be mixed down to mono."),
143 QString(), QString(), QString(),
144 _("opus_accept_down_mix_on_export")) != KMessageBox::Continue)
145 {
146 return false;
147 }
148 m_downmix = DOWNMIX_MONO;
149 } else if (tracks > 2) {
150 // downmix from more than stereo to stereo
151 if (Kwave::MessageBox::warningContinueCancel(
152 widget,
153 i18n("Surround bitrate would be less than 32kBit/sec per "
154 "channel, this file should be mixed down to stereo."),
155 QString(), QString(), QString(),
156 _("opus_accept_down_mix_on_export")) != KMessageBox::Continue)
157 {
158 return false;
159 }
160 m_downmix = DOWNMIX_STEREO;
161 }
162 }
163 if (m_downmix == DOWNMIX_AUTO) // if still "auto"
164 m_downmix = DOWNMIX_OFF; // then switch it off
165
166 switch (m_downmix) {
167 case DOWNMIX_MONO: m_encoder_channels = 1; break;
168 case DOWNMIX_STEREO: m_encoder_channels = 2; break;
169 default: m_encoder_channels = tracks; break;
170 }
171
172 if (m_encoder_channels != tracks) {
173 // create a channel mixer
174 m_channel_mixer = new(std::nothrow)
175 Kwave::ChannelMixer(tracks, m_encoder_channels);
176 Q_ASSERT(m_channel_mixer);
177 if (!m_channel_mixer || !m_channel_mixer->init()) {
178 qWarning("creating channel mixer failed");
179 return false;
180 }
181
182 // connect it to the end of the current preprocessing queue
183 // (normally this is the original sample source)
184 if (!Kwave::connect(
185 *m_last_queue_element, SIGNAL(output(Kwave::SampleArray)),
186 *m_channel_mixer, SLOT(input(Kwave::SampleArray))))
187 {
188 qWarning("connecting the channel mixer failed");
189 return false;
190 }
191 m_last_queue_element = m_channel_mixer;
192 }
193
194 return true;
195 }
196
197 /***************************************************************************/
setupBitrate(QWidget * widget,unsigned int tracks)198 bool Kwave::OpusEncoder::setupBitrate(QWidget *widget, unsigned int tracks)
199 {
200 int bitrate_nominal = m_info.contains(Kwave::INF_BITRATE_NOMINAL) ?
201 QVariant(m_info.get(Kwave::INF_BITRATE_NOMINAL)).toInt() : -1;
202 int bitrate_lower = m_info.contains(Kwave::INF_BITRATE_LOWER) ?
203 QVariant(m_info.get(Kwave::INF_BITRATE_LOWER)).toInt() : -1;
204 int bitrate_upper = m_info.contains(Kwave::INF_BITRATE_UPPER) ?
205 QVariant(m_info.get(Kwave::INF_BITRATE_UPPER)).toInt() : -1;
206
207 // prefer bitrates in this order:
208 // nominal -> upper -> lower -> "auto" (-1)
209 int bitrate = -1;
210 if (bitrate_nominal > 0) bitrate = bitrate_nominal;
211 else if (bitrate_upper > 0) bitrate = bitrate_upper;
212 else if (bitrate_lower > 0) bitrate = bitrate_lower;
213
214 if ((bitrate > 0) && ((bitrate > (BITRATE_MAX * Kwave::toInt(tracks)))
215 || (bitrate < BITRATE_MIN)))
216 {
217 int bitrate_new =
218 qBound<int>(BITRATE_MIN, bitrate, BITRATE_MAX * tracks);
219
220 if (Kwave::MessageBox::warningContinueCancel(
221 widget,
222 i18nc("%1=original bitrate, %2=new/limited bitrate",
223 "Bitrate %1 kBit/sec is out of range, "
224 "limited to %2 kBit/sec",
225 bitrate / 1000,
226 bitrate_new / 1000),
227 QString(), QString(), QString(),
228 _("opus_bitrate_limit")) != KMessageBox::Continue)
229 {
230 return false;
231 }
232 }
233
234 if (bitrate > 0)
235 qDebug(" OpusEncoder: bitrate %d bits/sec (configured)", bitrate);
236 m_bitrate = bitrate;
237 return true;
238 }
239
240 /***************************************************************************/
setupCodingRate(QWidget * widget,unsigned int tracks,double rate)241 bool Kwave::OpusEncoder::setupCodingRate(QWidget *widget,
242 unsigned int tracks, double rate)
243 {
244 Q_UNUSED(widget)
245
246 Q_ASSERT(!m_rate_converter);
247
248 int rate_orig = Kwave::toInt(rate);
249 int rate_supp = Kwave::opus_next_sample_rate(rate_orig);
250
251 m_coding_rate = rate_supp;
252
253 if (rate_orig == rate_supp) {
254 qDebug(" OpusEncoder: using sample rate %d", rate_orig);
255 return true; // no conversion needed :-)
256 }
257
258 double rate_from = static_cast<double>(rate_orig);
259 double rate_to = static_cast<double>(rate_supp);
260 double ratio = rate_to / rate_from;
261
262 qDebug(" OpusEncoder: converting sample rate: %d -> %d",
263 rate_orig, rate_supp);
264
265 // range check: conversion ration must be between 1/256 and 256
266 if ((ratio < (1.0 / 256.0)) || (ratio > 256.0)) {
267 int lowest = qMin<int>(SAMPLE_RATE_MIN,
268 Kwave::toInt(ceil( rate_to / 256.0)));
269 int highest = qMax<int>(Kwave::toInt(floor(rate_to * 256.0)),
270 SAMPLE_RATE_MAX);
271 Kwave::MessageBox::sorry(
272 widget,
273 i18nc("%1=requested sample rate, "
274 "%2=lowest supported, %3=highest supported",
275 "Sample rate %1 samples/sec is out of range,\n"
276 "supported are %2 ... %3 samples/sec.",
277 rate_supp, lowest, highest),
278 QString()
279 );
280 return false;
281 }
282
283 // create a new rate converter
284 m_rate_converter = new(std::nothrow)
285 Kwave::MultiTrackSource<Kwave::RateConverter, true>(tracks);
286 Q_ASSERT(m_rate_converter);
287 if (!m_rate_converter)
288 return false;
289
290 m_rate_converter->setAttribute(
291 SLOT(setRatio(QVariant)),
292 QVariant(ratio)
293 );
294
295 // connect the rate converter to the end of the current preprocessing
296 // queue/ (normally this is either the original sample source or
297 // a channel mixer)
298 if (!Kwave::connect(
299 *m_last_queue_element, SIGNAL(output(Kwave::SampleArray)),
300 *m_rate_converter, SLOT(input(Kwave::SampleArray))))
301 {
302 qWarning("connecting the rate converter failed");
303 return false;
304 }
305 m_last_queue_element = m_rate_converter;
306
307 return true;
308 }
309
310 /***************************************************************************/
setupEncoder(QWidget * widget,unsigned int tracks,double rate)311 bool Kwave::OpusEncoder::setupEncoder(QWidget *widget, unsigned int tracks,
312 double rate)
313 {
314 // get the frame size in ms if present,
315 // otherwise fall back to the default of 20ms
316 // (supported values are 2.5, 5, 10, 20, 40, or 60 ms)
317 qreal ms_per_frame = 20.0; // default is 20ms
318 if (m_info.contains(INF_OPUS_FRAME_LEN)) {
319 double len = m_info.get(INF_OPUS_FRAME_LEN).toDouble();
320 if (len >= 60)
321 ms_per_frame = 60.0;
322 else if (len >= 40)
323 ms_per_frame = 40.0;
324 else if (len >= 20)
325 ms_per_frame = 20.0;
326 else if (len >= 5)
327 ms_per_frame = 5;
328 else
329 ms_per_frame = 2.5;
330 qDebug(" OpusEncoder: %0.1f ms/frame", ms_per_frame);
331 } else {
332 ms_per_frame = 20.0; // <- default
333 qDebug(" OpusEncoder: %0.1f ms/frame (default)", ms_per_frame);
334 }
335
336 // calculate the frame size in samples from the frame duration in ms
337 // = frame_length [ms] * bitrate [bits/sec] / 1000 [ms/sec]
338 m_frame_size = Kwave::toUint(
339 (ms_per_frame * m_coding_rate) / 1000);
340
341 if (tracks > 255) {
342 qWarning("too many tracks: %u, supported: 255", tracks);
343 return false; // more than 255 tracks are not supported
344 }
345
346 // fill out all header fields
347 m_opus_header.channels = static_cast<quint8>(tracks);
348 m_opus_header.preskip = 0;
349 m_opus_header.sample_rate = static_cast<quint32>(rate);
350 m_opus_header.gain = 0;
351 m_opus_header.channel_mapping = 255;
352 m_opus_header.streams = static_cast<quint8>(tracks);
353 m_opus_header.coupled = 0;
354
355 // determine channel mapping and coupling
356 quint8 force_narrow = 0x00;
357 if (tracks <= 8) {
358 /* apply a mapping as done in opusenc.c from opus-tools-0.1.5 */
359 static const quint8 opusenc_streams[8][10]= {
360 /* Coupled, NB_bitmap, mapping...*/
361 /* 1 */ {0, 0, 0 },
362 /* 2 */ {1, 0, 0, 1 },
363 /* 3 */ {1, 0, 0, 2, 1 },
364 /* 4 */ {2, 0, 0, 1, 2, 3 },
365 /* 5 */ {2, 0, 0, 4, 1, 2, 3 },
366 /* 6 */ {2, 1 << 3, 0, 4, 1, 2, 3, 5 },
367 /* 7 */ {2, 1 << 4, 0, 4, 1, 2, 3, 5, 6 },
368 /* 8 */ {3, 1 << 4, 0, 6, 1, 2, 3, 4, 5, 7 }
369 };
370 for (unsigned int i = 0; i < tracks; i++)
371 m_opus_header.map[i] = opusenc_streams[tracks - 1][i + 2];
372 force_narrow = opusenc_streams[tracks - 1][1];
373 m_opus_header.coupled = opusenc_streams[tracks - 1][0];
374 m_opus_header.streams = static_cast<quint8>(
375 tracks - m_opus_header.coupled);
376 m_opus_header.channel_mapping = (m_opus_header.streams > 1);
377
378 qDebug(" OpusEncoder: %d stream(s) / %d coupled (mapping=%d)",
379 m_opus_header.streams, m_opus_header.coupled,
380 m_opus_header.channel_mapping);
381 } else {
382 /* map all channels 1:1 */
383 for (quint8 i = 0; i < m_opus_header.channels; ++i)
384 m_opus_header.map[i] = i;
385 qDebug(" OpusEncoder: mapping channels 1:1");
386 }
387
388 // allocate a packet buffer
389 m_max_frame_bytes = ((1275 * 3) + 7) * m_opus_header.streams;
390 qDebug(" OpusEncoder: max frame size %u bytes", m_max_frame_bytes);
391 Q_ASSERT(!m_packet_buffer);
392 m_packet_buffer = static_cast<unsigned char *>(malloc(m_max_frame_bytes));
393 if (!m_packet_buffer) {
394 Kwave::MessageBox::error(widget, i18n("Out of memory"));
395 return false;
396 }
397
398 // initialize the Opus encoder:
399 // frame sizes < 10ms can only use the MDCT modes,
400 // so we switch on RESTRICTED_LOWDELAY to save the extra 2.5ms of codec
401 // lookahead when we'll be using only small frames
402
403 int err = OPUS_ALLOC_FAIL;
404 Q_ASSERT(!m_encoder);
405 m_encoder = opus_multistream_encoder_create(
406 m_coding_rate,
407 tracks,
408 m_opus_header.streams,
409 m_opus_header.coupled,
410 m_opus_header.map,
411 (ms_per_frame < 10.0) ? OPUS_APPLICATION_RESTRICTED_LOWDELAY :
412 OPUS_APPLICATION_AUDIO,
413 &err
414 );
415 if (err != OPUS_OK) {
416 Kwave::MessageBox::error(widget, Kwave::opus_error(err),
417 i18n("Opus encoder failed"));
418 return false;
419 }
420
421 if (force_narrow) {
422 for (unsigned int i = 0; i < m_opus_header.streams; i++ ) {
423 if (force_narrow & (1 << i)) {
424 ::OpusEncoder *oe = Q_NULLPTR;
425
426 opus_multistream_encoder_ctl(
427 m_encoder,
428 OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, i, &oe
429 );
430
431 int err_ctl = opus_encoder_ctl(oe,
432 OPUS_SET_MAX_BANDWIDTH_REQUEST, OPUS_BANDWIDTH_NARROWBAND);
433
434 if (err_ctl != OPUS_OK) {
435 Kwave::MessageBox::error(widget, Kwave::opus_error(err_ctl),
436 i18n("Opus encoder failed"));
437 return false;
438 }
439 }
440 }
441 }
442
443 // allocate a buffer to be used as input of the encoder
444 m_encoder_input = static_cast<float *>(
445 malloc(sizeof(float) * m_frame_size * tracks));
446 if (!m_encoder_input) {
447 Kwave::MessageBox::error(widget, i18n("Out of memory"));
448 return false;
449 }
450
451 return true;
452 }
453
454 /***************************************************************************/
setupBitrateMode(QWidget * widget)455 bool Kwave::OpusEncoder::setupBitrateMode(QWidget *widget)
456 {
457 const bool with_cvbr = false;
458 int err;
459
460 // determine a reasonable bitrate in case we still use "autodetect"
461 if (m_bitrate < 0) {
462 m_bitrate = (64000 * m_opus_header.streams) +
463 (32000 * m_opus_header.coupled);
464 m_bitrate = qBound<int>(500, m_bitrate, 256000);
465 qDebug(" OpusEncoder: bitrate %d bits/sec (auto)", m_bitrate);
466 }
467
468 err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_BITRATE(
469 static_cast<opus_int32>(m_bitrate)));
470 if (err != OPUS_OK) {
471 Kwave::MessageBox::error(widget,
472 i18n("Opus encoder failed setting bitrate: '%1'",
473 Kwave::opus_error(err)));
474 return false;
475 }
476
477 int bitrate_mode = m_info.get(INF_BITRATE_MODE).toInt();
478 bool with_hard_cbr = (bitrate_mode == BITRATE_MODE_CBR_HARD);
479
480 err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_VBR(
481 static_cast<opus_int32>(with_hard_cbr ? 0 : 1)));
482 if (err != OPUS_OK) {
483 Kwave::MessageBox::error(widget,
484 i18n("Opus encoder failed configuring VBR mode: '%1'",
485 Kwave::opus_error(err)));
486 return false;
487 }
488
489 if (!with_hard_cbr ) {
490 err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_VBR_CONSTRAINT(
491 static_cast<opus_int32>(with_cvbr ? 1 : 0)));
492 if (err != OPUS_OK) {
493 Kwave::MessageBox::error(widget,
494 i18n("Opus encoder failed configuring VBR constraint: '%1'",
495 Kwave::opus_error(err)));
496 return false;
497 }
498 }
499
500 return true;
501 }
502
503 /***************************************************************************/
open(QWidget * widget,const Kwave::FileInfo & info,Kwave::MultiTrackReader & src)504 bool Kwave::OpusEncoder::open(QWidget *widget, const Kwave::FileInfo &info,
505 Kwave::MultiTrackReader &src)
506 {
507 // get info: tracks, sample rate, bitrate(s)
508 m_info = info;
509 const unsigned int src_tracks = m_info.tracks();
510 const double sample_rate = m_info.rate();
511 int err;
512
513 // reset everything to defaults
514 m_downmix = DOWNMIX_AUTO;
515 m_bitrate = -1;
516 m_coding_rate = 0;
517 m_extra_out = 0;
518 m_frame_size = 0;
519 memset(&m_opus_header, 0x00, sizeof(m_opus_header));
520 memset(&m_opus_header.map, 0xFF, sizeof(m_opus_header.map));
521 m_max_frame_bytes = 0;
522 m_last_queue_element = &src;
523
524 // get the desired bitrate
525 if (!setupBitrate(widget, src_tracks))
526 return false;
527
528 // determine the down mixing mode
529 // and set up the mixer if necessary
530 if (!setupDownMix(widget, src_tracks, m_bitrate))
531 return false;
532
533 // determine the decoding sample rate
534 // and set up the rate converter if necessary
535 if (!setupCodingRate(widget, m_encoder_channels, sample_rate))
536 return false;
537
538 // set up mapping, packet size and encoder
539 if (!setupEncoder(widget, m_encoder_channels, sample_rate))
540 return false;
541
542 // set up bitrate mode (e.g. VBR, ABR, ...)
543 if (!setupBitrateMode(widget))
544 return false;
545
546 // create a sample buffer at the end of the filter chain
547 m_buffer = new(std::nothrow)
548 Kwave::MultiTrackSink<Kwave::SampleBuffer, true>(m_encoder_channels);
549 Q_ASSERT(m_buffer);
550 if (!m_buffer) {
551 qWarning("cannot create sample buffer");
552 return false;
553 }
554 if (!Kwave::connect(
555 *m_last_queue_element, SIGNAL(output(Kwave::SampleArray)),
556 *m_buffer, SLOT(input(Kwave::SampleArray))) )
557 {
558 qWarning("failed to connect sample buffer");
559 return false;
560 }
561
562 // set up the encoder complexity (ignore errors)
563 opus_int32 complexity = DEFAULT_COMPLEXITY;
564 err = opus_multistream_encoder_ctl(m_encoder,
565 OPUS_SET_COMPLEXITY(complexity));
566 if (err != OPUS_OK) {
567 qWarning("OpusEncoder: failed setting encoder complexity: '%s'",
568 DBG(Kwave::opus_error(err)));
569 }
570
571 // set up the expected loss [percent] (ignore errors)
572 opus_int32 expect_loss = 0;
573 err = opus_multistream_encoder_ctl(m_encoder,
574 OPUS_SET_PACKET_LOSS_PERC(expect_loss));
575 if (err != OPUS_OK) {
576 qWarning("OpusEncoder: failed setting expected loss: '%s'",
577 DBG(Kwave::opus_error(err)));
578 }
579
580 #ifdef OPUS_SET_LSB_DEPTH
581 // set up the LSB depth
582 opus_int32 bits = qBound<unsigned int>(8, m_info.bits(), 24);
583 err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_LSB_DEPTH(bits));
584 if (err != OPUS_OK) {
585 qWarning("OpusEncoder: failed setting LSB depth loss: '%s'",
586 DBG(Kwave::opus_error(err)));
587 }
588 #endif /* OPUS_SET_LSB_DEPTH */
589
590 // get the lookahead value
591 opus_int32 lookahead;
592 err = opus_multistream_encoder_ctl(m_encoder,
593 OPUS_GET_LOOKAHEAD(&lookahead));
594 if (err != OPUS_OK) {
595 Kwave::MessageBox::error(widget,
596 i18n("Opus encoder failed getting lookahead value: '%1'",
597 Kwave::opus_error(err)));
598 return false;
599 }
600
601 // regardless of the rate we're coding at the ogg timestamping/skip is
602 // always timed at 48000 kBit/s
603 m_opus_header.preskip = static_cast<quint16>(
604 lookahead * (48000.0 / m_coding_rate));
605 qDebug(" OpusEncoder: preskip=%d", m_opus_header.preskip);
606
607 /* Extra samples that need to be read to compensate for the pre-skip */
608 m_extra_out = lookahead;
609
610 // set up our packet->stream encoder
611 // pick a random serial number; that way we can more likely build
612 // chained streams just by concatenation
613 QRandomGenerator rnd(QTime::currentTime().msec());
614 ogg_stream_init(&m_os, rnd.generate());
615
616 return true;
617 }
618
619 /***************************************************************************/
_writeInt(QBuffer & buffer,quint32 value)620 static inline void _writeInt(QBuffer &buffer, quint32 value)
621 {
622 quint32 x = qToLittleEndian<quint32>(value);
623 buffer.write(reinterpret_cast<const char *>(&x), sizeof(x));
624 }
625
626 /***************************************************************************/
writeOpusHeader(QIODevice & dst)627 bool Kwave::OpusEncoder::writeOpusHeader(QIODevice &dst)
628 {
629 Kwave::opus_header_t header;
630 unsigned int len;
631
632 // create an Opus header, using correct byte order
633 memset(&header, 0x00, sizeof(header));
634 memset(&header.map, 0xFF, sizeof(header.map));
635
636 memcpy(&(header.magic[0]), "OpusHead", 8);
637 header.version = 1;
638 header.channels = m_opus_header.channels;
639 header.preskip = qToLittleEndian<quint16>(m_opus_header.preskip);
640 header.sample_rate = qToLittleEndian<quint32>(m_opus_header.sample_rate);
641 header.gain = qToLittleEndian<quint16>(m_opus_header.gain);
642 header.channel_mapping = m_opus_header.channel_mapping;
643 len = 19; // bytes so far
644 if (m_opus_header.channel_mapping) {
645 header.streams = m_opus_header.streams;
646 header.coupled = m_opus_header.coupled;
647 len += 2;
648
649 for (quint8 i = 0; i < m_opus_header.channels; ++i)
650 header.map[i] = m_opus_header.map[i];
651 len += m_opus_header.channels;
652 }
653
654 // write the header into the ogg stream
655 m_op.packet = reinterpret_cast<unsigned char *>(&header);
656 m_op.bytes = len;
657 m_op.b_o_s = 1;
658 m_op.e_o_s = 0;
659 m_op.granulepos = 0;
660 m_op.packetno = 0;
661 ogg_stream_packetin(&m_os, &m_op);
662
663 while (ogg_stream_flush(&m_os, &m_og)) {
664 dst.write(reinterpret_cast<char *>(m_og.header),
665 m_og.header_len);
666 dst.write(reinterpret_cast<char *>(m_og.body),
667 m_og.body_len);
668 }
669
670 return true;
671 }
672
673 /***************************************************************************/
writeOpusTags(QIODevice & dst)674 bool Kwave::OpusEncoder::writeOpusTags(QIODevice &dst)
675 {
676 QBuffer buffer;
677
678 buffer.open(QBuffer::ReadWrite);
679
680 // let the header start with the magic string "OpusTags"
681 buffer.write("OpusTags", 8);
682
683 // write the vendor string == name + version of the encoder library
684 const char *opus_version = opus_get_version_string();
685 quint32 len = quint32(strlen(opus_version));
686 _writeInt(buffer, len);
687 buffer.write(opus_version, len);
688
689 // iterate over all known properties and collect them in a list
690 QList<QByteArray> tags;
691 len = 0;
692
693 for (VorbisCommentMap::const_iterator it(m_comments_map.constBegin());
694 it != m_comments_map.constEnd(); ++it)
695 {
696 const QString &key = it.key();
697 Kwave::FileProperty property = it.value();
698 if (!m_info.contains(property)) continue; // skip if not present
699
700 // convert the value into a byte array, UTF-8 encoded
701 QString str = key + _("=") + m_info.get(property).toString();
702 QByteArray v = str.toUtf8();
703
704 // make sure that the "ENCODER" tag is at the start of the list
705 if ((property == INF_SOFTWARE) && (!tags.isEmpty()))
706 tags.prepend(v);
707 else
708 tags.append(v);
709
710 len += (4 + v.size()); // sum up the data length
711 }
712
713 // write the number of user tags
714 _writeInt(buffer, tags.count());
715
716 // serialize the tags into the buffer
717 foreach (const QByteArray &tag, tags) {
718 _writeInt(buffer, tag.size());
719 buffer.write(tag);
720 }
721
722 m_op.packet = reinterpret_cast<unsigned char *>(buffer.buffer().data());
723 m_op.bytes = static_cast<long int>(buffer.size());
724 m_op.b_o_s = 0;
725 m_op.e_o_s = 0;
726 m_op.granulepos = 0;
727 m_op.packetno = 1;
728 ogg_stream_packetin(&m_os, &m_op);
729
730 while (ogg_stream_flush(&m_os, &m_og)) {
731 if (!writeOggPage(dst)) return false;
732 }
733
734 return true;
735 }
736
737 /***************************************************************************/
writeHeader(QIODevice & dst)738 bool Kwave::OpusEncoder::writeHeader(QIODevice &dst)
739 {
740 if (!writeOpusHeader(dst))
741 return false;
742
743 if (!writeOpusTags(dst))
744 return false;
745
746 return true;
747 }
748
749 /***************************************************************************/
writeOggPage(QIODevice & dst)750 bool Kwave::OpusEncoder::writeOggPage(QIODevice &dst)
751 {
752 qint64 n;
753
754 n = dst.write(reinterpret_cast<char *>(m_og.header), m_og.header_len);
755 if (n != m_og.header_len) {
756 qWarning("OpusEncoder: I/O error writing header, len=%u, written=%u",
757 static_cast<unsigned int>(n),
758 static_cast<unsigned int>(m_og.header_len));
759 return false; // write error ?
760 }
761
762 n = dst.write(reinterpret_cast<char *>(m_og.body), m_og.body_len);
763 if (n != m_og.body_len) {
764 qWarning("OpusEncoder: I/O error writing body, len=%u, written=%u",
765 static_cast<unsigned int>(n),
766 static_cast<unsigned int>(m_og.body_len));
767 return false; // write error ?
768 }
769
770 // update the progress bar
771 QApplication::processEvents();
772
773 return true;
774 }
775
776 /***************************************************************************/
fillInBuffer(Kwave::MultiTrackReader & src)777 unsigned int Kwave::OpusEncoder::fillInBuffer(Kwave::MultiTrackReader &src)
778 {
779 unsigned int min_count = m_frame_size + 1; // will be used as "invalid"
780
781 for (unsigned int t = 0; t < m_encoder_channels; ++t) {
782 Kwave::SampleBuffer *buf = m_buffer->at(t);
783 Q_ASSERT(buf);
784 if (!buf) return 0;
785
786 unsigned int count = 0;
787 unsigned int rest = m_frame_size;
788 while (rest) {
789
790 // while buffer is empty and source is not at eof:
791 // trigger the start of the chain to produce some data
792 while (!buf->available() && !src.eof())
793 src.goOn();
794 const unsigned int avail = buf->available();
795 if (!avail) break; // reached EOF
796
797 // while there is something in the current buffer
798 // and some rest is still to do
799 unsigned int len = qMin<unsigned int>(rest, avail);
800 const sample_t *s = buf->get(len);
801 Q_ASSERT(s);
802 if (!s) break;
803
804 // fill the frame data
805 rest -= len;
806 count += len;
807 float *p = m_encoder_input + t;
808 while (len--) {
809 *p = sample2float(*(s++));
810 p += m_encoder_channels;
811 }
812 }
813 if (count < min_count) min_count = count;
814 }
815
816 // take the minimum number of samples if valid, otherwise zero (eof?)
817 unsigned int n = (min_count <= m_frame_size) ? min_count : 0;
818
819 // if we were not able to fill a complete frame, we probably are at eof
820 // and have some space to pad with extra samples to compensate preskip
821 unsigned int extra_out = m_extra_out;
822 while ((n < m_frame_size) && extra_out) {
823 Q_ASSERT(src.eof());
824 for (unsigned int t = 0; t < m_encoder_channels; ++t) {
825 m_encoder_input[(n * m_encoder_channels) + t] = 0.0;
826 }
827 extra_out--;
828 n++;
829 }
830
831 return n;
832 }
833
834 /***************************************************************************/
encode(Kwave::MultiTrackReader & src,QIODevice & dst)835 bool Kwave::OpusEncoder::encode(Kwave::MultiTrackReader &src,
836 QIODevice &dst)
837 {
838 long int eos = 0;
839 opus_int64 nb_encoded = 0;
840 opus_int64 nb_samples = -1;
841 opus_int64 total_bytes = 0;
842 opus_int64 total_samples = 0;
843 ogg_int64_t enc_granulepos = 0;
844 ogg_int64_t last_granulepos = 0;
845 ogg_int32_t packet_id = 1;
846 int last_segments = 0;
847 const int max_ogg_delay = 48000; /* 48kHz samples */
848
849 Q_ASSERT(m_encoder);
850 Q_ASSERT(m_encoder_input);
851
852 Q_UNUSED(dst)
853
854 /* Main encoding loop (one frame per iteration) */
855 while (!m_op.e_o_s && !src.isCanceled()) {
856 int size_segments = 0;
857
858 packet_id++;
859
860 if (nb_samples < 0) {
861 nb_samples = fillInBuffer(src);
862 total_samples += nb_samples;
863 m_op.e_o_s = (nb_samples < m_frame_size) ? 1 : 0;
864 }
865 m_op.e_o_s |= eos; // eof from last pass
866
867 // pad the rest of the frame with zeroes if necessary
868 if (nb_samples < m_frame_size ) {
869 const unsigned int pad_from =
870 Kwave::toUint(nb_samples * m_encoder_channels);
871 const unsigned int pad_to =
872 Kwave::toUint(m_frame_size * m_encoder_channels);
873 for (unsigned int pos = pad_from; pos < pad_to; pos++ )
874 m_encoder_input[pos] = 0;
875 }
876
877 /* encode current frame */
878 int nbBytes = opus_multistream_encode_float(
879 m_encoder,
880 m_encoder_input,
881 m_frame_size,
882 m_packet_buffer,
883 m_max_frame_bytes
884 );
885 if (nbBytes < 0 ) {
886 qWarning("Opus encoder failed: '%s'",
887 DBG(Kwave::opus_error(nbBytes)));
888 return false;
889 }
890
891 nb_encoded += m_frame_size;
892 enc_granulepos += m_frame_size * 48000 / m_coding_rate;
893 total_bytes += nbBytes;
894 size_segments = (nbBytes + 255) / 255;
895
896 // flush early if adding this packet would make us end up with a
897 // continued page which we wouldn't have otherwise
898 while (( ((size_segments <= 255) &&
899 (last_segments + size_segments > 255)) ||
900 (enc_granulepos - last_granulepos > max_ogg_delay)) &&
901 #ifdef HAVE_OGG_STREAM_FLUSH_FILL
902 ogg_stream_flush_fill(&m_os, &m_og, 255 * 255))
903 #else /* HAVE_OGG_STREAM_FLUSH_FILL */
904 ogg_stream_flush(&m_os, &m_og))
905 #endif /* HAVE_OGG_STREAM_FLUSH_FILL */
906 {
907 if (ogg_page_packets(&m_og) != 0)
908 last_granulepos = ogg_page_granulepos(&m_og);
909
910 last_segments -= m_og.header[26];
911
912 if (!writeOggPage(dst)) {
913 qWarning("Opus encoder: I/O error");
914 return false;
915 }
916 }
917
918 // the downside of early reading is if the input is an exact
919 // multiple of the frame_size you'll get an extra frame that needs
920 // to get cropped off. The downside of late reading is added delay.
921 // If your ogg_delay is 120ms or less we'll assume you want the
922 // low delay behavior.
923 if ((!m_op.e_o_s ) && (max_ogg_delay > 5760)) {
924 nb_samples = fillInBuffer(src);
925 total_samples += nb_samples;
926 if (nb_samples < m_frame_size) eos = 1;
927 if (nb_samples == 0) m_op.e_o_s = 1;
928 } else {
929 nb_samples = -1;
930 }
931
932 m_op.packet = m_packet_buffer;
933 m_op.packetno = packet_id;
934 m_op.bytes = nbBytes;
935 m_op.b_o_s = 0;
936 m_op.granulepos = enc_granulepos;
937 if (m_op.e_o_s) {
938 // compute the final GP as ceil(len*48k/input_rate). When a
939 // resampling decoder does the matching floor(len*input/48k)
940 // conversion the length will be exactly the same as the input.
941 sample_index_t length = m_info.length();
942 double rate = m_info.rate();
943 m_op.granulepos = static_cast<ogg_int64_t>(
944 ceil((static_cast<double>(length) * 48000.0) / rate) +
945 m_opus_header.preskip);
946 }
947 ogg_stream_packetin(&m_os, &m_op);
948 last_segments += size_segments;
949
950 // If the stream is over or we're sure that the delayed flush will
951 // fire, go ahead and flush now to avoid adding delay.
952 while ((m_op.e_o_s || (enc_granulepos +
953 ((m_frame_size * 48000) / m_coding_rate ) -
954 last_granulepos > max_ogg_delay) || (last_segments >= 255)) ?
955 #ifdef HAVE_OGG_STREAM_FLUSH_FILL
956 ogg_stream_flush_fill(&m_os, &m_og, 255 * 255) :
957 ogg_stream_pageout_fill(&m_os, &m_og, 255 * 255))
958 #else /* HAVE_OGG_STREAM_FLUSH_FILL */
959 /*Libogg > 1.2.2 allows us to achieve lower overhead by
960 producing larger pages. For 20ms frames this is only relevant
961 above ~32kbit/sec.*/
962 ogg_stream_flush(&m_os, &m_og) :
963 ogg_stream_pageout(&m_os, &m_og))
964 #endif /* HAVE_OGG_STREAM_FLUSH_FILL */
965 {
966 if (ogg_page_packets(&m_og) != 0)
967 last_granulepos = ogg_page_granulepos(&m_og);
968
969 last_segments -= m_og.header[26];
970 if (!writeOggPage(dst)) {
971 qWarning("Opus encoder: I/O error");
972 return false;
973 }
974 }
975 }
976
977 return true;
978 }
979
980 /***************************************************************************/
close()981 void Kwave::OpusEncoder::close()
982 {
983 if (m_channel_mixer) delete m_channel_mixer;
984 m_channel_mixer = Q_NULLPTR;
985
986 if (m_rate_converter) delete m_rate_converter;
987 m_rate_converter = Q_NULLPTR;
988
989 if (m_buffer) delete m_buffer;
990 m_buffer = Q_NULLPTR;
991
992 if (m_encoder) opus_multistream_encoder_destroy(m_encoder);
993 m_encoder = Q_NULLPTR;
994
995 ogg_stream_clear(&m_os);
996
997 if (m_packet_buffer) free(m_packet_buffer);
998 m_packet_buffer = Q_NULLPTR;
999
1000 if (m_encoder_input) free(m_encoder_input);
1001 m_encoder_input = Q_NULLPTR;
1002
1003 m_last_queue_element = Q_NULLPTR;
1004 }
1005
1006 /***************************************************************************/
1007 /***************************************************************************/
1008