1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-10 22:31:40 +02:00

Fix possible crash on corrupted video file

This commit is contained in:
Ivan Savenko
2025-01-07 15:05:25 +00:00
parent 228b585527
commit ed2825d4f2
2 changed files with 34 additions and 9 deletions

View File

@@ -59,8 +59,18 @@ static si64 lodSeek(void * opaque, si64 pos, int whence)
return data->seek(pos); return data->seek(pos);
} }
static void logFFmpegError(int errorCode)
{
std::array<char, AV_ERROR_MAX_STRING_SIZE> errorMessage{};
av_strerror(errorCode, errorMessage.data(), errorMessage.size());
logGlobal->warn("Failed to open video file! Reason: %s", errorMessage.data());
}
[[noreturn]] static void throwFFmpegError(int errorCode) [[noreturn]] static void throwFFmpegError(int errorCode)
{ {
logFFmpegError(errorCode);
std::array<char, AV_ERROR_MAX_STRING_SIZE> errorMessage{}; std::array<char, AV_ERROR_MAX_STRING_SIZE> errorMessage{};
av_strerror(errorCode, errorMessage.data(), errorMessage.size()); av_strerror(errorCode, errorMessage.data(), errorMessage.size());
@@ -95,7 +105,7 @@ bool FFMpegStream::openInput(const VideoPath & videoToOpen)
return input != nullptr; return input != nullptr;
} }
void FFMpegStream::openContext() bool FFMpegStream::openContext()
{ {
static const int BUFFER_SIZE = 4096; static const int BUFFER_SIZE = 4096;
input->seek(0); input->seek(0);
@@ -109,13 +119,21 @@ void FFMpegStream::openContext()
int avfopen = avformat_open_input(&formatContext, "dummyFilename", nullptr, nullptr); int avfopen = avformat_open_input(&formatContext, "dummyFilename", nullptr, nullptr);
if(avfopen != 0) if(avfopen != 0)
throwFFmpegError(avfopen); {
logFFmpegError(avfopen);
return false;
}
// Retrieve stream information // Retrieve stream information
int findStreamInfo = avformat_find_stream_info(formatContext, nullptr); int findStreamInfo = avformat_find_stream_info(formatContext, nullptr);
if(avfopen < 0) if(avfopen < 0)
throwFFmpegError(findStreamInfo); {
logFFmpegError(findStreamInfo);
return false;
}
return true;
} }
void FFMpegStream::openCodec(int desiredStreamIndex) void FFMpegStream::openCodec(int desiredStreamIndex)
@@ -169,10 +187,13 @@ const AVFrame * FFMpegStream::getCurrentFrame() const
return frame; return frame;
} }
void CVideoInstance::openVideo() bool CVideoInstance::openVideo()
{ {
openContext(); if (!openContext())
return false;
openCodec(findVideoStream()); openCodec(findVideoStream());
return true;
} }
void CVideoInstance::prepareOutput(float scaleFactor, bool useTextureOutput) void CVideoInstance::prepareOutput(float scaleFactor, bool useTextureOutput)
@@ -526,7 +547,9 @@ std::pair<std::unique_ptr<ui8 []>, si64> CAudioInstance::extractAudio(const Vide
{ {
if (!openInput(videoToOpen)) if (!openInput(videoToOpen))
return { nullptr, 0}; return { nullptr, 0};
openContext();
if (!openContext())
return { nullptr, 0};
int audioStreamIndex = findAudioStream(); int audioStreamIndex = findAudioStream();
if (audioStreamIndex == -1) if (audioStreamIndex == -1)
@@ -653,7 +676,9 @@ std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, float
if (!result->openInput(name)) if (!result->openInput(name))
return nullptr; return nullptr;
result->openVideo(); if (!result->openVideo())
return nullptr;
result->prepareOutput(scaleFactor, false); result->prepareOutput(scaleFactor, false);
result->loadNextFrame(); // prepare 1st frame result->loadNextFrame(); // prepare 1st frame

View File

@@ -42,7 +42,7 @@ class FFMpegStream : boost::noncopyable
AVFrame * frame = nullptr; AVFrame * frame = nullptr;
protected: protected:
void openContext(); bool openContext();
void openCodec(int streamIndex); void openCodec(int streamIndex);
int findVideoStream() const; int findVideoStream() const;
@@ -91,7 +91,7 @@ public:
CVideoInstance(); CVideoInstance();
~CVideoInstance(); ~CVideoInstance();
void openVideo(); bool openVideo();
bool loadNextFrame(); bool loadNextFrame();
double timeStamp() final; double timeStamp() final;