Fix planar audio playback (for example .flac).

Also add some more crash information logging.

Fixes #4120.
This commit is contained in:
John Preston 2017-12-08 12:57:43 +04:00
parent 827784e3b2
commit e273695cc9
2 changed files with 45 additions and 6 deletions

View File

@ -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 {

View File

@ -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;