Kaynağa Gözat

Fix possible crash on corrupted video file

Ivan Savenko 9 ay önce
ebeveyn
işleme
ed2825d4f2
2 değiştirilmiş dosya ile 34 ekleme ve 9 silme
  1. 32 7
      client/media/CVideoHandler.cpp
  2. 2 2
      client/media/CVideoHandler.h

+ 32 - 7
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<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)
 {
+	logFFmpegError(errorCode);
+
 	std::array<char, AV_ERROR_MAX_STRING_SIZE> 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<std::unique_ptr<ui8 []>, 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<IVideoInstance> 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
 

+ 2 - 2
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;