From 574f4a73cba3665c4dc18f306bbad711f17a13ae Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 12 Dec 2017 16:03:51 +0400 Subject: [PATCH] Add some checks to video sound stream decoding. --- .../media/media_child_ffmpeg_loader.cpp | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Telegram/SourceFiles/media/media_child_ffmpeg_loader.cpp b/Telegram/SourceFiles/media/media_child_ffmpeg_loader.cpp index 04fbd11005..cef1911cfb 100644 --- a/Telegram/SourceFiles/media/media_child_ffmpeg_loader.cpp +++ b/Telegram/SourceFiles/media/media_child_ffmpeg_loader.cpp @@ -20,10 +20,25 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "media/media_child_ffmpeg_loader.h" +#include "core/crash_reports.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 + VideoSoundData::~VideoSoundData() { if (context) { avcodec_close(context); @@ -179,11 +194,48 @@ AudioPlayerLoader::ReadResult ChildFFMpegLoader::readFromReadyFrame(QByteArray & return ReadResult::Error; } } + + // See the same check in media_audio_ffmpeg_loader.cpp. + if (_frame->extended_data[1] == nullptr) { + const auto params = _parentData->context; + if (IsPlanarFormat(params->sample_fmt) && 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->sample_fmt + ).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->sample_fmt + ).arg(_frame->channel_layout + ).arg(_frame->channels + ).arg(_frame->format + ).arg(ptrdiff_t(_frame->data[0]) + ).arg(ptrdiff_t(_frame->extended_data[0]) + ).arg(ptrdiff_t(_frame->data[1]) + ); + CrashReports::SetAnnotation(key, value); + } + } + if ((res = swr_convert(_swrContext, _dstSamplesData, dstSamples, (const uint8_t**)_frame->extended_data, _frame->nb_samples)) < 0) { char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; 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)); + CrashReports::ClearAnnotation(key); + } + int32 resultLen = av_samples_get_buffer_size(0, AudioToChannels, res, AudioToFormat, 1); result.append((const char*)_dstSamplesData[0], resultLen); samplesAdded += resultLen / _sampleSize;