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:
@@ -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
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user