1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #include "media/audio/media_audio_capture.h"
9
10 #include "media/audio/media_audio_ffmpeg_loader.h"
11 #include "ffmpeg/ffmpeg_utility.h"
12 #include "base/timer.h"
13
14 #include <al.h>
15 #include <alc.h>
16
17 #include <numeric>
18
19 namespace Media {
20 namespace Capture {
21 namespace {
22
23 constexpr auto kCaptureFrequency = Player::kDefaultFrequency;
24 constexpr auto kCaptureSkipDuration = crl::time(400);
25 constexpr auto kCaptureFadeInDuration = crl::time(300);
26 constexpr auto kCaptureBufferSlice = 256 * 1024;
27 constexpr auto kCaptureUpdateDelta = crl::time(100);
28
29 Instance *CaptureInstance = nullptr;
30
ErrorHappened(ALCdevice * device)31 bool ErrorHappened(ALCdevice *device) {
32 ALenum errCode;
33 if ((errCode = alcGetError(device)) != ALC_NO_ERROR) {
34 LOG(("Audio Capture Error: %1, %2").arg(errCode).arg((const char *)alcGetString(device, errCode)));
35 return true;
36 }
37 return false;
38 }
39
40 } // namespace
41
42 class Instance::Inner final : public QObject {
43 public:
44 Inner(QThread *thread);
45 ~Inner();
46
47 void start(Fn<void(Update)> updated, Fn<void()> error);
48 void stop(Fn<void(Result&&)> callback = nullptr);
49
50 private:
51 void process();
52
53 [[nodiscard]] bool processFrame(int32 offset, int32 framesize);
54 void fail();
55
56 [[nodiscard]] bool writeFrame(AVFrame *frame);
57
58 // Writes the packets till EAGAIN is got from av_receive_packet()
59 // Returns number of packets written or -1 on error
60 [[nodiscard]] int writePackets();
61
62 Fn<void(Update)> _updated;
63 Fn<void()> _error;
64
65 struct Private;
66 const std::unique_ptr<Private> d;
67 base::Timer _timer;
68 QByteArray _captured;
69
70 };
71
Start()72 void Start() {
73 Assert(CaptureInstance == nullptr);
74 CaptureInstance = new Instance();
75 instance()->check();
76 }
77
Finish()78 void Finish() {
79 delete base::take(CaptureInstance);
80 }
81
Instance()82 Instance::Instance() : _inner(std::make_unique<Inner>(&_thread)) {
83 CaptureInstance = this;
84 _thread.start();
85 }
86
start()87 void Instance::start() {
88 _updates.fire_done();
89 InvokeQueued(_inner.get(), [=] {
90 _inner->start([=](Update update) {
91 crl::on_main(this, [=] {
92 _updates.fire_copy(update);
93 });
94 }, [=] {
95 crl::on_main(this, [=] {
96 _updates.fire_error({});
97 });
98 });
99 crl::on_main(this, [=] {
100 _started = true;
101 });
102 });
103 }
104
stop(Fn<void (Result &&)> callback)105 void Instance::stop(Fn<void(Result&&)> callback) {
106 InvokeQueued(_inner.get(), [=] {
107 if (!callback) {
108 _inner->stop();
109 crl::on_main(this, [=] { _started = false; });
110 return;
111 }
112 _inner->stop([=](Result &&result) {
113 crl::on_main([=, result = std::move(result)]() mutable {
114 callback(std::move(result));
115 _started = false;
116 });
117 });
118 });
119 }
120
check()121 void Instance::check() {
122 _available = false;
123 if (auto device = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) {
124 if (!QString::fromUtf8(device).isEmpty()) {
125 _available = true;
126 return;
127 }
128 }
129 LOG(("Audio Error: No capture device found!"));
130 }
131
~Instance()132 Instance::~Instance() {
133 InvokeQueued(_inner.get(), [copy = base::take(_inner)] {
134 });
135 _thread.quit();
136 _thread.wait();
137 }
138
instance()139 Instance *instance() {
140 return CaptureInstance;
141 }
142
143 struct Instance::Inner::Private {
144 ALCdevice *device = nullptr;
145 AVOutputFormat *fmt = nullptr;
146 uchar *ioBuffer = nullptr;
147 AVIOContext *ioContext = nullptr;
148 AVFormatContext *fmtContext = nullptr;
149 AVStream *stream = nullptr;
150 AVCodec *codec = nullptr;
151 AVCodecContext *codecContext = nullptr;
152 bool opened = false;
153 bool processing = false;
154
155 int srcSamples = 0;
156 int dstSamples = 0;
157 int maxDstSamples = 0;
158 int dstSamplesSize = 0;
159 int fullSamples = 0;
160 uint8_t **srcSamplesData = nullptr;
161 uint8_t **dstSamplesData = nullptr;
162 SwrContext *swrContext = nullptr;
163
164 int32 lastUpdate = 0;
165 uint16 levelMax = 0;
166
167 QByteArray data;
168 int32 dataPos = 0;
169
170 int64 waveformMod = 0;
171 int64 waveformEach = (kCaptureFrequency / 100);
172 uint16 waveformPeak = 0;
173 QVector<uchar> waveform;
174
_read_dataMedia::Capture::Instance::Inner::Private175 static int _read_data(void *opaque, uint8_t *buf, int buf_size) {
176 auto l = reinterpret_cast<Private*>(opaque);
177
178 int32 nbytes = qMin(l->data.size() - l->dataPos, int32(buf_size));
179 if (nbytes <= 0) {
180 return 0;
181 }
182
183 memcpy(buf, l->data.constData() + l->dataPos, nbytes);
184 l->dataPos += nbytes;
185 return nbytes;
186 }
187
_write_dataMedia::Capture::Instance::Inner::Private188 static int _write_data(void *opaque, uint8_t *buf, int buf_size) {
189 auto l = reinterpret_cast<Private*>(opaque);
190
191 if (buf_size <= 0) return 0;
192 if (l->dataPos + buf_size > l->data.size()) l->data.resize(l->dataPos + buf_size);
193 memcpy(l->data.data() + l->dataPos, buf, buf_size);
194 l->dataPos += buf_size;
195 return buf_size;
196 }
197
_seek_dataMedia::Capture::Instance::Inner::Private198 static int64_t _seek_data(void *opaque, int64_t offset, int whence) {
199 auto l = reinterpret_cast<Private*>(opaque);
200
201 int32 newPos = -1;
202 switch (whence) {
203 case SEEK_SET: newPos = offset; break;
204 case SEEK_CUR: newPos = l->dataPos + offset; break;
205 case SEEK_END: newPos = l->data.size() + offset; break;
206 case AVSEEK_SIZE: {
207 // Special whence for determining filesize without any seek.
208 return l->data.size();
209 } break;
210 }
211 if (newPos < 0) {
212 return -1;
213 }
214 l->dataPos = newPos;
215 return l->dataPos;
216 }
217 };
218
Inner(QThread * thread)219 Instance::Inner::Inner(QThread *thread)
220 : d(std::make_unique<Private>())
221 , _timer(thread, [=] { process(); }) {
222 moveToThread(thread);
223 }
224
~Inner()225 Instance::Inner::~Inner() {
226 stop();
227 }
228
fail()229 void Instance::Inner::fail() {
230 stop();
231 if (const auto error = base::take(_error)) {
232 InvokeQueued(this, error);
233 }
234 }
235
start(Fn<void (Update)> updated,Fn<void ()> error)236 void Instance::Inner::start(Fn<void(Update)> updated, Fn<void()> error) {
237 _updated = std::move(updated);
238 _error = std::move(error);
239
240 // Start OpenAL Capture
241 d->device = alcCaptureOpenDevice(nullptr, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5);
242 if (!d->device) {
243 LOG(("Audio Error: capture device not present!"));
244 fail();
245 return;
246 }
247 alcCaptureStart(d->device);
248 if (ErrorHappened(d->device)) {
249 alcCaptureCloseDevice(d->device);
250 d->device = nullptr;
251 fail();
252 return;
253 }
254
255 // Create encoding context
256
257 d->ioBuffer = (uchar*)av_malloc(FFmpeg::kAVBlockSize);
258
259 d->ioContext = avio_alloc_context(d->ioBuffer, FFmpeg::kAVBlockSize, 1, static_cast<void*>(d.get()), &Private::_read_data, &Private::_write_data, &Private::_seek_data);
260 int res = 0;
261 char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
262 const AVOutputFormat *fmt = nullptr;
263 void *i = nullptr;
264 while ((fmt = av_muxer_iterate(&i))) {
265 if (fmt->name == qstr("opus")) {
266 break;
267 }
268 }
269 if (!fmt) {
270 LOG(("Audio Error: Unable to find opus AVOutputFormat for capture"));
271 fail();
272 return;
273 }
274
275 if ((res = avformat_alloc_output_context2(&d->fmtContext, (AVOutputFormat*)fmt, 0, 0)) < 0) {
276 LOG(("Audio Error: Unable to avformat_alloc_output_context2 for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
277 fail();
278 return;
279 }
280 d->fmtContext->pb = d->ioContext;
281 d->fmtContext->flags |= AVFMT_FLAG_CUSTOM_IO;
282 d->opened = true;
283
284 // Add audio stream
285 d->codec = avcodec_find_encoder(fmt->audio_codec);
286 if (!d->codec) {
287 LOG(("Audio Error: Unable to avcodec_find_encoder for capture"));
288 fail();
289 return;
290 }
291 d->stream = avformat_new_stream(d->fmtContext, d->codec);
292 if (!d->stream) {
293 LOG(("Audio Error: Unable to avformat_new_stream for capture"));
294 fail();
295 return;
296 }
297 d->stream->id = d->fmtContext->nb_streams - 1;
298 d->codecContext = avcodec_alloc_context3(d->codec);
299 if (!d->codecContext) {
300 LOG(("Audio Error: Unable to avcodec_alloc_context3 for capture"));
301 fail();
302 return;
303 }
304
305 av_opt_set_int(d->codecContext, "refcounted_frames", 1, 0);
306
307 d->codecContext->sample_fmt = AV_SAMPLE_FMT_FLTP;
308 d->codecContext->bit_rate = 32000;
309 d->codecContext->channel_layout = AV_CH_LAYOUT_MONO;
310 d->codecContext->sample_rate = kCaptureFrequency;
311 d->codecContext->channels = 1;
312
313 if (d->fmtContext->oformat->flags & AVFMT_GLOBALHEADER) {
314 d->codecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
315 }
316
317 // Open audio stream
318 if ((res = avcodec_open2(d->codecContext, d->codec, nullptr)) < 0) {
319 LOG(("Audio Error: Unable to avcodec_open2 for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
320 fail();
321 return;
322 }
323
324 // Alloc source samples
325
326 d->srcSamples = (d->codecContext->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ? 10000 : d->codecContext->frame_size;
327 //if ((res = av_samples_alloc_array_and_samples(&d->srcSamplesData, 0, d->codecContext->channels, d->srcSamples, d->codecContext->sample_fmt, 0)) < 0) {
328 // LOG(("Audio Error: Unable to av_samples_alloc_array_and_samples for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
329 // onStop(false);
330 // emit error();
331 // return;
332 //}
333 // Using _captured directly
334
335 // Prepare resampling
336 d->swrContext = swr_alloc();
337 if (!d->swrContext) {
338 fprintf(stderr, "Could not allocate resampler context\n");
339 exit(1);
340 }
341
342 av_opt_set_int(d->swrContext, "in_channel_count", d->codecContext->channels, 0);
343 av_opt_set_int(d->swrContext, "in_sample_rate", d->codecContext->sample_rate, 0);
344 av_opt_set_sample_fmt(d->swrContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
345 av_opt_set_int(d->swrContext, "out_channel_count", d->codecContext->channels, 0);
346 av_opt_set_int(d->swrContext, "out_sample_rate", d->codecContext->sample_rate, 0);
347 av_opt_set_sample_fmt(d->swrContext, "out_sample_fmt", d->codecContext->sample_fmt, 0);
348
349 if ((res = swr_init(d->swrContext)) < 0) {
350 LOG(("Audio Error: Unable to swr_init for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
351 fail();
352 return;
353 }
354
355 d->maxDstSamples = d->srcSamples;
356 if ((res = av_samples_alloc_array_and_samples(&d->dstSamplesData, 0, d->codecContext->channels, d->maxDstSamples, d->codecContext->sample_fmt, 0)) < 0) {
357 LOG(("Audio Error: Unable to av_samples_alloc_array_and_samples for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
358 fail();
359 return;
360 }
361 d->dstSamplesSize = av_samples_get_buffer_size(0, d->codecContext->channels, d->maxDstSamples, d->codecContext->sample_fmt, 0);
362
363 if ((res = avcodec_parameters_from_context(d->stream->codecpar, d->codecContext)) < 0) {
364 LOG(("Audio Error: Unable to avcodec_parameters_from_context for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
365 fail();
366 return;
367 }
368
369 // Write file header
370 if ((res = avformat_write_header(d->fmtContext, 0)) < 0) {
371 LOG(("Audio Error: Unable to avformat_write_header for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
372 fail();
373 return;
374 }
375
376 _timer.callEach(50);
377 _captured.clear();
378 _captured.reserve(kCaptureBufferSlice);
379 DEBUG_LOG(("Audio Capture: started!"));
380 }
381
stop(Fn<void (Result &&)> callback)382 void Instance::Inner::stop(Fn<void(Result&&)> callback) {
383 if (!_timer.isActive()) {
384 return; // in stop() already
385 }
386 _timer.cancel();
387
388 const auto needResult = (callback != nullptr);
389 const auto hadDevice = (d->device != nullptr);
390 if (hadDevice) {
391 alcCaptureStop(d->device);
392 if (d->processing) {
393 Assert(!needResult); // stop in the middle of processing - error.
394 } else {
395 process(); // get last data
396 }
397 alcCaptureCloseDevice(d->device);
398 d->device = nullptr;
399 }
400
401 // Write what is left
402 if (needResult && !_captured.isEmpty()) {
403 auto fadeSamples = kCaptureFadeInDuration * kCaptureFrequency / 1000;
404 auto capturedSamples = static_cast<int>(_captured.size() / sizeof(short));
405 if ((_captured.size() % sizeof(short)) || (d->fullSamples + capturedSamples < kCaptureFrequency) || (capturedSamples < fadeSamples)) {
406 d->fullSamples = 0;
407 d->dataPos = 0;
408 d->data.clear();
409 d->waveformMod = 0;
410 d->waveformPeak = 0;
411 d->waveform.clear();
412 } else {
413 float64 coef = 1. / fadeSamples, fadedFrom = 0;
414 for (short *ptr = ((short*)_captured.data()) + capturedSamples, *end = ptr - fadeSamples; ptr != end; ++fadedFrom) {
415 --ptr;
416 *ptr = qRound(fadedFrom * coef * *ptr);
417 }
418 if (capturedSamples % d->srcSamples) {
419 int32 s = _captured.size();
420 _captured.resize(s + (d->srcSamples - (capturedSamples % d->srcSamples)) * sizeof(short));
421 memset(_captured.data() + s, 0, _captured.size() - s);
422 }
423
424 int32 framesize = d->srcSamples * d->codecContext->channels * sizeof(short), encoded = 0;
425 while (_captured.size() >= encoded + framesize) {
426 if (!processFrame(encoded, framesize)) {
427 break;
428 }
429 encoded += framesize;
430 }
431 // Drain the codec.
432 if (!writeFrame(nullptr) || encoded != _captured.size()) {
433 d->fullSamples = 0;
434 d->dataPos = 0;
435 d->data.clear();
436 d->waveformMod = 0;
437 d->waveformPeak = 0;
438 d->waveform.clear();
439 }
440 }
441 }
442 DEBUG_LOG(("Audio Capture: "
443 "stopping (need result: %1), size: %2, samples: %3"
444 ).arg(Logs::b(callback != nullptr)
445 ).arg(d->data.size()
446 ).arg(d->fullSamples));
447 _captured = QByteArray();
448
449 // Finish stream
450 if (needResult && hadDevice) {
451 av_write_trailer(d->fmtContext);
452 }
453
454 QByteArray result = d->fullSamples ? d->data : QByteArray();
455 VoiceWaveform waveform;
456 qint32 samples = d->fullSamples;
457 if (needResult && samples && !d->waveform.isEmpty()) {
458 int64 count = d->waveform.size(), sum = 0;
459 if (count >= Player::kWaveformSamplesCount) {
460 QVector<uint16> peaks;
461 peaks.reserve(Player::kWaveformSamplesCount);
462
463 uint16 peak = 0;
464 for (int32 i = 0; i < count; ++i) {
465 uint16 sample = uint16(d->waveform.at(i)) * 256;
466 if (peak < sample) {
467 peak = sample;
468 }
469 sum += Player::kWaveformSamplesCount;
470 if (sum >= count) {
471 sum -= count;
472 peaks.push_back(peak);
473 peak = 0;
474 }
475 }
476
477 auto sum = std::accumulate(peaks.cbegin(), peaks.cend(), 0LL);
478 peak = qMax(int32(sum * 1.8 / peaks.size()), 2500);
479
480 waveform.resize(peaks.size());
481 for (int32 i = 0, l = peaks.size(); i != l; ++i) {
482 waveform[i] = char(qMin(31U, uint32(qMin(peaks.at(i), peak)) * 31 / peak));
483 }
484 }
485 }
486 if (hadDevice) {
487 if (d->codecContext) {
488 avcodec_free_context(&d->codecContext);
489 d->codecContext = nullptr;
490 }
491 if (d->srcSamplesData) {
492 if (d->srcSamplesData[0]) {
493 av_freep(&d->srcSamplesData[0]);
494 }
495 av_freep(&d->srcSamplesData);
496 }
497 if (d->dstSamplesData) {
498 if (d->dstSamplesData[0]) {
499 av_freep(&d->dstSamplesData[0]);
500 }
501 av_freep(&d->dstSamplesData);
502 }
503 d->fullSamples = 0;
504 if (d->swrContext) {
505 swr_free(&d->swrContext);
506 d->swrContext = nullptr;
507 }
508 if (d->opened) {
509 avformat_close_input(&d->fmtContext);
510 d->opened = false;
511 }
512 if (d->ioContext) {
513 av_freep(&d->ioContext->buffer);
514 av_freep(&d->ioContext);
515 d->ioBuffer = nullptr;
516 } else if (d->ioBuffer) {
517 av_freep(&d->ioBuffer);
518 }
519 if (d->fmtContext) {
520 avformat_free_context(d->fmtContext);
521 d->fmtContext = nullptr;
522 }
523 d->fmt = nullptr;
524 d->stream = nullptr;
525 d->codec = nullptr;
526
527 d->lastUpdate = 0;
528 d->levelMax = 0;
529
530 d->dataPos = 0;
531 d->data.clear();
532
533 d->waveformMod = 0;
534 d->waveformPeak = 0;
535 d->waveform.clear();
536 }
537
538 if (needResult) {
539 callback({ result, waveform, samples });
540 }
541 }
542
process()543 void Instance::Inner::process() {
544 Expects(!d->processing);
545
546 d->processing = true;
547 const auto guard = gsl::finally([&] { d->processing = false; });
548
549 if (!d->device) {
550 _timer.cancel();
551 return;
552 }
553 ALint samples;
554 alcGetIntegerv(d->device, ALC_CAPTURE_SAMPLES, 1, &samples);
555 if (ErrorHappened(d->device)) {
556 fail();
557 return;
558 }
559 if (samples > 0) {
560 // Get samples from OpenAL
561 auto s = _captured.size();
562 auto news = s + static_cast<int>(samples * sizeof(short));
563 if (news / kCaptureBufferSlice > s / kCaptureBufferSlice) {
564 _captured.reserve(((news / kCaptureBufferSlice) + 1) * kCaptureBufferSlice);
565 }
566 _captured.resize(news);
567 alcCaptureSamples(d->device, (ALCvoid *)(_captured.data() + s), samples);
568 if (ErrorHappened(d->device)) {
569 fail();
570 return;
571 }
572
573 // Count new recording level and update view
574 auto skipSamples = kCaptureSkipDuration * kCaptureFrequency / 1000;
575 auto fadeSamples = kCaptureFadeInDuration * kCaptureFrequency / 1000;
576 auto levelindex = d->fullSamples + static_cast<int>(s / sizeof(short));
577 for (auto ptr = (const short*)(_captured.constData() + s), end = (const short*)(_captured.constData() + news); ptr < end; ++ptr, ++levelindex) {
578 if (levelindex > skipSamples) {
579 uint16 value = qAbs(*ptr);
580 if (levelindex < skipSamples + fadeSamples) {
581 value = qRound(value * float64(levelindex - skipSamples) / fadeSamples);
582 }
583 if (d->levelMax < value) {
584 d->levelMax = value;
585 }
586 }
587 }
588 qint32 samplesFull = d->fullSamples + _captured.size() / sizeof(short), samplesSinceUpdate = samplesFull - d->lastUpdate;
589 if (samplesSinceUpdate > kCaptureUpdateDelta * kCaptureFrequency / 1000) {
590 _updated(Update{ .samples = samplesFull, .level = d->levelMax });
591 d->lastUpdate = samplesFull;
592 d->levelMax = 0;
593 }
594 // Write frames
595 int32 framesize = d->srcSamples * d->codecContext->channels * sizeof(short), encoded = 0;
596 while (uint32(_captured.size()) >= encoded + framesize + fadeSamples * sizeof(short)) {
597 if (!processFrame(encoded, framesize)) {
598 return;
599 }
600 encoded += framesize;
601 }
602
603 // Collapse the buffer
604 if (encoded > 0) {
605 int32 goodSize = _captured.size() - encoded;
606 memmove(_captured.data(), _captured.constData() + encoded, goodSize);
607 _captured.resize(goodSize);
608 }
609 } else {
610 DEBUG_LOG(("Audio Capture: no samples to capture."));
611 }
612 }
613
processFrame(int32 offset,int32 framesize)614 bool Instance::Inner::processFrame(int32 offset, int32 framesize) {
615 // Prepare audio frame
616
617 if (framesize % sizeof(short)) { // in the middle of a sample
618 LOG(("Audio Error: Bad framesize in writeFrame() for capture, framesize %1, %2").arg(framesize));
619 fail();
620 return false;
621 }
622 auto samplesCnt = static_cast<int>(framesize / sizeof(short));
623
624 int res = 0;
625 char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
626
627 auto srcSamplesDataChannel = (short*)(_captured.data() + offset);
628 auto srcSamplesData = &srcSamplesDataChannel;
629
630 // memcpy(d->srcSamplesData[0], _captured.constData() + offset, framesize);
631 auto skipSamples = static_cast<int>(kCaptureSkipDuration * kCaptureFrequency / 1000);
632 auto fadeSamples = static_cast<int>(kCaptureFadeInDuration * kCaptureFrequency / 1000);
633 if (d->fullSamples < skipSamples + fadeSamples) {
634 int32 fadedCnt = qMin(samplesCnt, skipSamples + fadeSamples - d->fullSamples);
635 float64 coef = 1. / fadeSamples, fadedFrom = d->fullSamples - skipSamples;
636 short *ptr = srcSamplesDataChannel, *zeroEnd = ptr + qMin(samplesCnt, qMax(0, skipSamples - d->fullSamples)), *end = ptr + fadedCnt;
637 for (; ptr != zeroEnd; ++ptr, ++fadedFrom) {
638 *ptr = 0;
639 }
640 for (; ptr != end; ++ptr, ++fadedFrom) {
641 *ptr = qRound(fadedFrom * coef * *ptr);
642 }
643 }
644
645 d->waveform.reserve(d->waveform.size() + (samplesCnt / d->waveformEach) + 1);
646 for (short *ptr = srcSamplesDataChannel, *end = ptr + samplesCnt; ptr != end; ++ptr) {
647 uint16 value = qAbs(*ptr);
648 if (d->waveformPeak < value) {
649 d->waveformPeak = value;
650 }
651 if (++d->waveformMod == d->waveformEach) {
652 d->waveformMod -= d->waveformEach;
653 d->waveform.push_back(uchar(d->waveformPeak / 256));
654 d->waveformPeak = 0;
655 }
656 }
657
658 // Convert to final format
659
660 d->dstSamples = av_rescale_rnd(swr_get_delay(d->swrContext, d->codecContext->sample_rate) + d->srcSamples, d->codecContext->sample_rate, d->codecContext->sample_rate, AV_ROUND_UP);
661 if (d->dstSamples > d->maxDstSamples) {
662 d->maxDstSamples = d->dstSamples;
663 av_freep(&d->dstSamplesData[0]);
664 if ((res = av_samples_alloc(d->dstSamplesData, 0, d->codecContext->channels, d->dstSamples, d->codecContext->sample_fmt, 1)) < 0) {
665 LOG(("Audio Error: Unable to av_samples_alloc for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
666 fail();
667 return false;
668 }
669 d->dstSamplesSize = av_samples_get_buffer_size(0, d->codecContext->channels, d->maxDstSamples, d->codecContext->sample_fmt, 0);
670 }
671
672 if ((res = swr_convert(d->swrContext, d->dstSamplesData, d->dstSamples, (const uint8_t **)srcSamplesData, d->srcSamples)) < 0) {
673 LOG(("Audio Error: Unable to swr_convert for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
674 fail();
675 return false;
676 }
677
678 // Write audio frame
679
680 AVFrame *frame = av_frame_alloc();
681
682 frame->format = d->codecContext->sample_fmt;
683 frame->channels = d->codecContext->channels;
684 frame->channel_layout = d->codecContext->channel_layout;
685 frame->sample_rate = d->codecContext->sample_rate;
686 frame->nb_samples = d->dstSamples;
687 frame->pts = av_rescale_q(d->fullSamples, AVRational { 1, d->codecContext->sample_rate }, d->codecContext->time_base);
688
689 avcodec_fill_audio_frame(frame, d->codecContext->channels, d->codecContext->sample_fmt, d->dstSamplesData[0], d->dstSamplesSize, 0);
690
691 if (!writeFrame(frame)) {
692 return false;
693 }
694
695 d->fullSamples += samplesCnt;
696
697 av_frame_free(&frame);
698 return true;
699 }
700
writeFrame(AVFrame * frame)701 bool Instance::Inner::writeFrame(AVFrame *frame) {
702 int res = 0;
703 char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
704
705 res = avcodec_send_frame(d->codecContext, frame);
706 if (res == AVERROR(EAGAIN)) {
707 const auto packetsWritten = writePackets();
708 if (packetsWritten < 0) {
709 if (frame && packetsWritten == AVERROR_EOF) {
710 LOG(("Audio Error: EOF in packets received when EAGAIN was got in avcodec_send_frame()"));
711 fail();
712 return false;
713 }
714 return true;
715 } else if (!packetsWritten) {
716 LOG(("Audio Error: No packets received when EAGAIN was got in avcodec_send_frame()"));
717 fail();
718 return false;
719 }
720 res = avcodec_send_frame(d->codecContext, frame);
721 }
722 if (res < 0) {
723 LOG(("Audio Error: Unable to avcodec_send_frame for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
724 fail();
725 return false;
726 }
727
728 if (!frame) { // drain
729 if ((res = writePackets()) != AVERROR_EOF) {
730 LOG(("Audio Error: not EOF in packets received when draining the codec, result %1").arg(res));
731 fail();
732 return false;
733 }
734 }
735 return true;
736 }
737
writePackets()738 int Instance::Inner::writePackets() {
739 AVPacket *pkt = av_packet_alloc();
740 const auto guard = gsl::finally([&] { av_packet_free(&pkt); });
741
742 int res = 0;
743 char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
744
745 int written = 0;
746 do {
747 if ((res = avcodec_receive_packet(d->codecContext, pkt)) < 0) {
748 if (res == AVERROR(EAGAIN)) {
749 return written;
750 } else if (res == AVERROR_EOF) {
751 return res;
752 }
753 LOG(("Audio Error: Unable to avcodec_receive_packet for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
754 fail();
755 return res;
756 }
757
758 av_packet_rescale_ts(pkt, d->codecContext->time_base, d->stream->time_base);
759 pkt->stream_index = d->stream->index;
760 if ((res = av_interleaved_write_frame(d->fmtContext, pkt)) < 0) {
761 LOG(("Audio Error: Unable to av_interleaved_write_frame for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
762 fail();
763 return -1;
764 }
765
766 ++written;
767 av_packet_unref(pkt);
768 } while (true);
769 return written;
770 }
771
772 } // namespace Capture
773 } // namespace Media
774