146 lines
3.6 KiB
C++
146 lines
3.6 KiB
C++
#ifndef ECLIPT_SUBTITLE_H
|
|
#define ECLIPT_SUBTITLE_H
|
|
|
|
#include "Frame.h"
|
|
#include <string>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <cstdint>
|
|
|
|
namespace eclipt {
|
|
|
|
enum class SubtitleType {
|
|
SRT,
|
|
VTT,
|
|
ASS,
|
|
SSA,
|
|
DVBSub,
|
|
DVB_Teletext,
|
|
EIA_608
|
|
};
|
|
|
|
struct SubtitleCue {
|
|
int64_t start_time = 0;
|
|
int64_t end_time = 0;
|
|
std::string text;
|
|
std::vector<std::string> lines;
|
|
int style_index = -1;
|
|
|
|
bool isValid() const { return !text.empty() && end_time > start_time; }
|
|
bool isActive(int64_t pts) const {
|
|
return pts >= start_time && pts < end_time;
|
|
}
|
|
};
|
|
|
|
struct SubtitleStyle {
|
|
std::string font_name;
|
|
int font_size = 24;
|
|
uint32_t primary_color = 0xFFFFFFFF;
|
|
uint32_t secondary_color = 0xFF000000;
|
|
uint32_t outline_color = 0xFF000000;
|
|
uint32_t back_color = 0x00000000;
|
|
int bold = 0;
|
|
int italic = 0;
|
|
int underline = 0;
|
|
int strikeout = 0;
|
|
double margin_l = 0;
|
|
double margin_r = 0;
|
|
double margin_v = 0;
|
|
int alignment = 2;
|
|
double scale_x = 1.0;
|
|
double scale_y = 1.0;
|
|
};
|
|
|
|
struct RenderedSubtitle {
|
|
VideoFrame frame;
|
|
int64_t pts = 0;
|
|
int64_t duration = 0;
|
|
bool has_ass_events = false;
|
|
|
|
RenderedSubtitle() = default;
|
|
bool isValid() const { return frame.isValid(); }
|
|
};
|
|
|
|
class ISubtitleRenderer {
|
|
public:
|
|
virtual ~ISubtitleRenderer() = default;
|
|
|
|
virtual bool initialize(int width, int height) = 0;
|
|
virtual void shutdown() = 0;
|
|
|
|
virtual bool loadSubtitles(const std::string& path) = 0;
|
|
virtual bool loadSubtitles(const uint8_t* data, size_t size, SubtitleType type) = 0;
|
|
virtual void clearSubtitles() = 0;
|
|
|
|
virtual void setStyle(const SubtitleStyle& style) = 0;
|
|
virtual SubtitleStyle getStyle() const = 0;
|
|
|
|
virtual RenderedSubtitle render(int64_t pts) = 0;
|
|
virtual const SubtitleCue* getCurrentCue(int64_t pts) const = 0;
|
|
|
|
virtual bool hasSubtitles() const = 0;
|
|
virtual size_t getCueCount() const = 0;
|
|
};
|
|
|
|
class SubtitleDecoder {
|
|
public:
|
|
SubtitleDecoder();
|
|
~SubtitleDecoder();
|
|
|
|
bool open(const std::string& url);
|
|
bool open(const uint8_t* data, size_t size, SubtitleType type);
|
|
void close();
|
|
|
|
bool isOpen() const { return is_open_; }
|
|
SubtitleType getType() const { return current_type_; }
|
|
|
|
std::vector<SubtitleCue> getCues() const { return cues_; }
|
|
const SubtitleCue* getCueAtTime(int64_t pts) const;
|
|
|
|
bool parse();
|
|
|
|
private:
|
|
bool is_open_ = false;
|
|
SubtitleType current_type_ = SubtitleType::SRT;
|
|
std::vector<SubtitleCue> cues_;
|
|
std::vector<uint8_t> data_;
|
|
|
|
bool parseSRT();
|
|
bool parseVTT();
|
|
bool parseASS();
|
|
|
|
int64_t parseTimestamp(const std::string& str);
|
|
std::vector<std::string> splitLines(const std::string& text);
|
|
};
|
|
|
|
class SubtitleRenderer : public ISubtitleRenderer {
|
|
public:
|
|
SubtitleRenderer();
|
|
~SubtitleRenderer() override;
|
|
|
|
bool initialize(int width, int height) override;
|
|
void shutdown() override;
|
|
|
|
bool loadSubtitles(const std::string& path) override;
|
|
bool loadSubtitles(const uint8_t* data, size_t size, SubtitleType type) override;
|
|
void clearSubtitles() override;
|
|
|
|
void setStyle(const SubtitleStyle& style) override;
|
|
SubtitleStyle getStyle() const override;
|
|
|
|
RenderedSubtitle render(int64_t pts) override;
|
|
const SubtitleCue* getCurrentCue(int64_t pts) const override;
|
|
|
|
bool hasSubtitles() const override;
|
|
size_t getCueCount() const override;
|
|
|
|
void setVideoParams(int width, int height, int fps_num, int fps_den);
|
|
|
|
private:
|
|
struct Impl;
|
|
std::unique_ptr<Impl> pImpl;
|
|
};
|
|
|
|
}
|
|
#endif
|