1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00
vcmi/client/widgets/VideoWidget.h
Ivan Savenko 9fbeacb688 Fix possible memory corruption in video player
Fixes two bugs, one was definitely happening, and 2nd one that is causing
undefined behavior and may work only in some std implementations

- VideoPlayer would attempt to access subtitles widget after VideoPlayer
itself was destroyed in onPlaybackFinished call
- std::function was destroyed from a function that is being called by
it. Replaced with 1-method interface to avoid usage of std::function in
this scenario
2024-12-07 15:37:03 +00:00

75 lines
2.0 KiB
C++

/*
* VideoWidget.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../lib/filesystem/ResourcePath.h"
#include "../lib/json/JsonNode.h"
class IVideoHolder;
class IVideoInstance;
class CMultiLineLabel;
class VideoWidgetBase : public CIntObject
{
std::unique_ptr<IVideoInstance> videoInstance;
std::unique_ptr<CMultiLineLabel> subTitle;
std::pair<std::unique_ptr<ui8[]>, si64> audioData = {nullptr, 0};
int audioHandle = -1;
bool playAudio = false;
float scaleFactor = 1.0;
JsonNode subTitleData;
void loadAudio(const VideoPath & file);
void startAudio();
void stopAudio();
std::string getSubTitleLine(double timestamp);
protected:
VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio);
VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio, float scaleFactor);
virtual void onPlaybackFinished() = 0;
void playVideo(const VideoPath & video);
public:
~VideoWidgetBase();
void activate() override;
void deactivate() override;
void show(Canvas & to) override;
void showAll(Canvas & to) override;
void tick(uint32_t msPassed) override;
void setPlaybackFinishedCallback(std::function<void()>);
};
class VideoWidget final: public VideoWidgetBase
{
VideoPath loopedVideo;
void onPlaybackFinished() final;
public:
VideoWidget(const Point & position, const VideoPath & prologue, const VideoPath & looped, bool playAudio);
VideoWidget(const Point & position, const VideoPath & looped, bool playAudio);
};
class VideoWidgetOnce final: public VideoWidgetBase
{
IVideoHolder * owner;
void onPlaybackFinished() final;
public:
VideoWidgetOnce(const Point & position, const VideoPath & video, bool playAudio, IVideoHolder * owner);
VideoWidgetOnce(const Point & position, const VideoPath & video, bool playAudio, float scaleFactor, IVideoHolder * owner);
};