From e273695cc90f6dea5399c499603e4425be261ba0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 8 Dec 2017 12:57:43 +0400 Subject: [PATCH] Fix planar audio playback (for example .flac). Also add some more crash information logging. Fixes #4120. --- Telegram/SourceFiles/logs.cpp | 3 ++ .../media/media_audio_ffmpeg_loader.cpp | 48 ++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 5db94cafc..b344ae046 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -1139,6 +1139,9 @@ namespace internal { } void setCrashAnnotation(const std::string &key, const QString &value) { + static QMutex mutex; + QMutexLocker lock(&mutex); + if (!value.trimmed().isEmpty()) { internal::ProcessAnnotations[key] = value.toUtf8().constData(); } else { diff --git a/Telegram/SourceFiles/media/media_audio_ffmpeg_loader.cpp b/Telegram/SourceFiles/media/media_audio_ffmpeg_loader.cpp index f29b89beb..fec669f74 100644 --- a/Telegram/SourceFiles/media/media_audio_ffmpeg_loader.cpp +++ b/Telegram/SourceFiles/media/media_audio_ffmpeg_loader.cpp @@ -20,10 +20,23 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "media/media_audio_ffmpeg_loader.h" +namespace { + constexpr AVSampleFormat AudioToFormat = AV_SAMPLE_FMT_S16; constexpr int64_t AudioToChannelLayout = AV_CH_LAYOUT_STEREO; constexpr int32 AudioToChannels = 2; +bool IsPlanarFormat(int format) { + return (format == AV_SAMPLE_FMT_U8P) + || (format == AV_SAMPLE_FMT_S16P) + || (format == AV_SAMPLE_FMT_S32P) + || (format == AV_SAMPLE_FMT_FLTP) + || (format == AV_SAMPLE_FMT_DBLP) + || (format == AV_SAMPLE_FMT_S64P); +} + +} // namespace + bool AbstractFFMpegLoader::open(qint64 &position) { if (!AudioPlayerLoader::openFile()) { return false; @@ -384,16 +397,33 @@ AudioPlayerLoader::ReadResult FFMpegLoader::readFromReadyFrame(QByteArray &resul // frame->channels = 1 // // So the frame just wasn't consistent with the codec params. - if (fmtContext->streams[streamId]->codecpar->channels > 1 - && frame->extended_data[1] == nullptr) { - auto params = fmtContext->streams[streamId]->codecpar; - LOG(("Audio Error: Inconsistent frame layout/channels in file, codec: (%1;%2), frame: (%3, %4)" + if (frame->extended_data[1] == nullptr) { + const auto params = fmtContext->streams[streamId]->codecpar; + if (IsPlanarFormat(params->format) && params->channels > 1) { + LOG(("Audio Error: Inconsistent frame layout/channels in file, codec: (%1;%2;%3), frame: (%4;%5;%6)." + ).arg(params->channel_layout + ).arg(params->channels + ).arg(params->format + ).arg(frame->channel_layout + ).arg(frame->channels + ).arg(frame->format + )); + return ReadResult::Error; + } else { + const auto key = "ffmpeg_" + std::to_string(ptrdiff_t(this)); + const auto value = QString("codec: (%1;%2;%3), frame: (%4;%5;%6), ptrs: (%7;%8;%9)" ).arg(params->channel_layout ).arg(params->channels + ).arg(params->format ).arg(frame->channel_layout ).arg(frame->channels - )); - return ReadResult::Error; + ).arg(frame->format + ).arg(ptrdiff_t(frame->data[0]) + ).arg(ptrdiff_t(frame->extended_data[0]) + ).arg(ptrdiff_t(frame->data[1]) + ); + SignalHandlers::setCrashAnnotation(key, value); + } } if ((res = swr_convert(swrContext, dstSamplesData, dstSamples, (const uint8_t**)frame->extended_data, frame->nb_samples)) < 0) { @@ -401,6 +431,12 @@ AudioPlayerLoader::ReadResult FFMpegLoader::readFromReadyFrame(QByteArray &resul LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return ReadResult::Error; } + + if (frame->extended_data[1] == nullptr) { + const auto key = "ffmpeg_" + std::to_string(ptrdiff_t(this)); + SignalHandlers::setCrashAnnotation(key, QString()); + } + int32 resultLen = av_samples_get_buffer_size(0, AudioToChannels, res, AudioToFormat, 1); result.append((const char*)dstSamplesData[0], resultLen); samplesAdded += resultLen / sampleSize;