Add some checks to video sound stream decoding.

This commit is contained in:
John Preston 2017-12-12 16:03:51 +04:00
parent 05e3ddce0c
commit 574f4a73cb
1 changed files with 52 additions and 0 deletions

View File

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