MythTV master
subtitlereader.cpp
Go to the documentation of this file.
3
4#ifdef DEBUG_SUBTITLES
5QString toString(const AVSubtitle& sub)
6{
7 auto start = QTime(0,0).addMSecs(sub.start_display_time);
8 auto end = QTime(0,0).addMSecs(sub.end_display_time);
9 return QString("%1-%2 (%3-%4)")
10 .arg(start.toString("HH:mm:ss.zzz"),
11 end.toString("HH:mm:ss.zzz"))
12 .arg(sub.start_display_time)
13 .arg(sub.end_display_time);
14}
15#endif
16
17// If the count of subtitle buffers is greater than this, force a clear
18static const int MAX_BUFFERS_BEFORE_CLEAR = 175; // 125 too low for karaoke
19
21 : m_parent(parent)
22{
25}
26
28{
31}
32
34{
35 m_avSubtitlesEnabled = enable;
36}
37
39{
41}
42
44{
46}
47
48void SubtitleReader::SeekFrame(int64_t ts, int flags)
49{
52 {
54 m_externalParser->SeekFrame(ts, flags);
55 }
56}
57
58bool SubtitleReader::AddAVSubtitle(AVSubtitle &subtitle,
59 bool fix_position,
60 bool is_selected_forced_track,
61 bool allow_forced,
62 bool isExternal)
63{
64 bool enableforced = false;
65 bool forced = false;
66
67 if (m_avSubtitlesEnabled && is_selected_forced_track)
68 {
69 FreeAVSubtitle(subtitle);
70 return enableforced;
71 }
72
73 for (unsigned i = 0; i < subtitle.num_rects; i++)
74 {
75 forced = forced || static_cast<bool>(subtitle.rects[i]->flags & AV_SUBTITLE_FLAG_FORCED);
76 }
77
78 if (!m_avSubtitlesEnabled && !isExternal)
79 {
80 if (!(is_selected_forced_track || forced))
81 {
82 FreeAVSubtitle(subtitle);
83 return enableforced;
84 }
85
86 if (!allow_forced)
87 {
88 LOG(VB_PLAYBACK, LOG_INFO,
89 "SubtitleReader: Ignoring forced AV subtitle.");
90 FreeAVSubtitle(subtitle);
91 return enableforced;
92 }
93
94 LOG(VB_PLAYBACK, LOG_INFO,
95 "SubtitleReader: Allowing forced AV subtitle.");
96 enableforced = true;
97 }
98
99 if ((m_textSubtitlesEnabled && !isExternal) ||
100 (m_avSubtitlesEnabled && isExternal))
101 {
102 FreeAVSubtitle(subtitle);
103 return enableforced;
104 }
105
106 // Sanity check to prevent seg fault
107 if (subtitle.num_rects > 1000)
108 {
109 FreeAVSubtitle(subtitle);
110 return enableforced;
111 }
112
113#ifdef DEBUG_SUBTITLES
114 if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_DEBUG))
115 {
116 LOG(VB_PLAYBACK, LOG_DEBUG,
117 QString("AddAVSubtitle adding sub %1").arg(toString(subtitle)));
118 }
119#endif
120
121 bool clearsubs = false;
122 m_avSubtitles.m_lock.lock();
123 m_avSubtitles.m_fixPosition = fix_position;
124 m_avSubtitles.m_buffers.push_back(subtitle);
125 // in case forced subtitles aren't displayed, avoid leaking by
126 // manually clearing the subtitles
127 if (!m_externalParser &&
129 {
130 LOG(VB_GENERAL, LOG_ERR,
131 QString("SubtitleReader: %1 AVSubtitles queued (more than %2) - clearing.")
132 .arg(m_avSubtitles.m_buffers.size())
134 clearsubs = true;
135 }
136 m_avSubtitles.m_lock.unlock();
137
138 if (clearsubs)
140
141 return enableforced;
142}
143
145{
146 m_avSubtitles.m_lock.lock();
147 while (!m_avSubtitles.m_buffers.empty())
148 {
150 m_avSubtitles.m_buffers.pop_front();
151 }
152 m_avSubtitles.m_lock.unlock();
153}
154
155void SubtitleReader::FreeAVSubtitle(AVSubtitle &subtitle)
156{
157 avsubtitle_free(&subtitle);
158}
159
160void SubtitleReader::LoadExternalSubtitles(const QString &subtitleFileName,
161 bool isInProgress)
162{
163 m_textSubtitles.SetInProgress(isInProgress);
164 if (!subtitleFileName.isEmpty())
165 {
166 m_externalParser = new TextSubtitleParser(this, subtitleFileName, &m_textSubtitles);
168 }
169}
170
172{
176 return -1;
177}
178
180{
182}
183
184QStringList SubtitleReader::GetRawTextSubtitles(std::chrono::milliseconds &duration)
185{
186 QMutexLocker lock(&m_rawTextSubtitles.m_lock);
187 if (m_rawTextSubtitles.m_buffers.empty())
188 return {};
189
191 QStringList result = m_rawTextSubtitles.m_buffers;
193 return result;
194}
195
196void SubtitleReader::AddRawTextSubtitle(const QStringList& list, std::chrono::milliseconds duration)
197{
198 if (!m_rawTextSubtitlesEnabled || list.empty())
199 return;
200
201 QMutexLocker lock(&m_rawTextSubtitles.m_lock);
205}
206
208{
209 QMutexLocker lock(&m_rawTextSubtitles.m_lock);
211}
MythDeque< AVSubtitle > m_buffers
bool m_fixPosition
std::chrono::milliseconds m_duration
QStringList m_buffers
AVSubtitles m_avSubtitles
void ClearRawTextSubtitles(void)
RawTextSubs m_rawTextSubtitles
static void FreeAVSubtitle(AVSubtitle &sub)
bool m_rawTextSubtitlesEnabled
~SubtitleReader() override
QStringList GetRawTextSubtitles(std::chrono::milliseconds &duration)
SubtitleReader(MythPlayer *parent)
void EnableRawTextSubtitles(bool enable)
TextSubtitles m_textSubtitles
bool AddAVSubtitle(AVSubtitle &subtitle, bool fix_position, bool is_selected_forced_track, bool allow_forced, bool isExternal)
void TextSubtitlesUpdated()
bool m_textSubtitlesEnabled
void ClearAVSubtitles(void)
void AddRawTextSubtitle(const QStringList &list, std::chrono::milliseconds duration)
TextSubtitleParser * m_externalParser
void LoadExternalSubtitles(const QString &subtitleFileName, bool isInProgress)
void EnableAVSubtitles(bool enable)
bool m_avSubtitlesEnabled
void EnableTextSubtitles(bool enable)
void SeekFrame(int64_t ts, int flags)
bool HasTextSubtitles(void)
int ReadNextSubtitle(void)
void LoadSubtitles(bool inBackground)
void SeekFrame(int64_t ts, int flags)
int ReadNextSubtitle(void)
Read the next subtitle in the AV stream.
void TextSubtitlesUpdated()
bool GetHasSubtitles() const
void SetInProgress(bool isInProgress)
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
static const int MAX_BUFFERS_BEFORE_CLEAR