From ed2825d4f2e2f565388052e94b0cbc1dccb43d9e Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 7 Jan 2025 15:05:25 +0000 Subject: [PATCH] Fix possible crash on corrupted video file --- client/media/CVideoHandler.cpp | 39 ++++++++++++++++++++++++++++------ client/media/CVideoHandler.h | 4 ++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/client/media/CVideoHandler.cpp b/client/media/CVideoHandler.cpp index 8ba26d5e1..84edc6943 100644 --- a/client/media/CVideoHandler.cpp +++ b/client/media/CVideoHandler.cpp @@ -59,8 +59,18 @@ static si64 lodSeek(void * opaque, si64 pos, int whence) return data->seek(pos); } +static void logFFmpegError(int errorCode) +{ + std::array 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) { + logFFmpegError(errorCode); + std::array errorMessage{}; av_strerror(errorCode, errorMessage.data(), errorMessage.size()); @@ -95,7 +105,7 @@ bool FFMpegStream::openInput(const VideoPath & videoToOpen) return input != nullptr; } -void FFMpegStream::openContext() +bool FFMpegStream::openContext() { static const int BUFFER_SIZE = 4096; input->seek(0); @@ -109,13 +119,21 @@ void FFMpegStream::openContext() int avfopen = avformat_open_input(&formatContext, "dummyFilename", nullptr, nullptr); if(avfopen != 0) - throwFFmpegError(avfopen); + { + logFFmpegError(avfopen); + return false; + } // Retrieve stream information int findStreamInfo = avformat_find_stream_info(formatContext, nullptr); if(avfopen < 0) - throwFFmpegError(findStreamInfo); + { + logFFmpegError(findStreamInfo); + return false; + } + + return true; } void FFMpegStream::openCodec(int desiredStreamIndex) @@ -169,10 +187,13 @@ const AVFrame * FFMpegStream::getCurrentFrame() const return frame; } -void CVideoInstance::openVideo() +bool CVideoInstance::openVideo() { - openContext(); + if (!openContext()) + return false; + openCodec(findVideoStream()); + return true; } void CVideoInstance::prepareOutput(float scaleFactor, bool useTextureOutput) @@ -526,7 +547,9 @@ std::pair, si64> CAudioInstance::extractAudio(const Vide { if (!openInput(videoToOpen)) return { nullptr, 0}; - openContext(); + + if (!openContext()) + return { nullptr, 0}; int audioStreamIndex = findAudioStream(); if (audioStreamIndex == -1) @@ -653,7 +676,9 @@ std::unique_ptr CVideoPlayer::open(const VideoPath & name, float if (!result->openInput(name)) return nullptr; - result->openVideo(); + if (!result->openVideo()) + return nullptr; + result->prepareOutput(scaleFactor, false); result->loadNextFrame(); // prepare 1st frame diff --git a/client/media/CVideoHandler.h b/client/media/CVideoHandler.h index 5047ba01a..a4229074b 100644 --- a/client/media/CVideoHandler.h +++ b/client/media/CVideoHandler.h @@ -42,7 +42,7 @@ class FFMpegStream : boost::noncopyable AVFrame * frame = nullptr; protected: - void openContext(); + bool openContext(); void openCodec(int streamIndex); int findVideoStream() const; @@ -91,7 +91,7 @@ public: CVideoInstance(); ~CVideoInstance(); - void openVideo(); + bool openVideo(); bool loadNextFrame(); double timeStamp() final;