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{
24}
25
27{
30}
31
33{
34 m_avSubtitlesEnabled = enable;
35}
36
38{
40}
41
43{
45}
46
47void SubtitleReader::SeekFrame(int64_t ts, int flags)
48{
51 {
53 m_externalParser->SeekFrame(ts, flags);
54 }
55}
56
57bool SubtitleReader::AddAVSubtitle(AVSubtitle &subtitle,
58 bool fix_position,
59 bool is_selected_forced_track,
60 bool allow_forced,
61 bool isExternal)
62{
63 bool enableforced = false;
64 bool forced = false;
65
66 if (m_avSubtitlesEnabled && is_selected_forced_track)
67 {
68 FreeAVSubtitle(subtitle);
69 return enableforced;
70 }
71
72 for (unsigned i = 0; i < subtitle.num_rects; i++)
73 {
74 forced = forced || static_cast<bool>(subtitle.rects[i]->flags & AV_SUBTITLE_FLAG_FORCED);
75 }
76
77 if (!m_avSubtitlesEnabled && !isExternal)
78 {
79 if (!(is_selected_forced_track || forced))
80 {
81 FreeAVSubtitle(subtitle);
82 return enableforced;
83 }
84
85 if (!allow_forced)
86 {
87 LOG(VB_PLAYBACK, LOG_INFO,
88 "SubtitleReader: Ignoring forced AV subtitle.");
89 FreeAVSubtitle(subtitle);
90 return enableforced;
91 }
92
93 LOG(VB_PLAYBACK, LOG_INFO,
94 "SubtitleReader: Allowing forced AV subtitle.");
95 enableforced = true;
96 }
97
98 if ((m_textSubtitlesEnabled && !isExternal) ||
99 (m_avSubtitlesEnabled && isExternal))
100 {
101 FreeAVSubtitle(subtitle);
102 return enableforced;
103 }
104
105 // Sanity check to prevent seg fault
106 if (subtitle.num_rects > 1000)
107 {
108 FreeAVSubtitle(subtitle);
109 return enableforced;
110 }
111
112#ifdef DEBUG_SUBTITLES
113 if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_DEBUG))
114 {
115 LOG(VB_PLAYBACK, LOG_DEBUG,
116 QString("AddAVSubtitle adding sub %1").arg(toString(subtitle)));
117 }
118#endif
119
120 bool clearsubs = false;
121 m_avSubtitles.m_lock.lock();
122 m_avSubtitles.m_fixPosition = fix_position;
123 m_avSubtitles.m_buffers.push_back(subtitle);
124 // in case forced subtitles aren't displayed, avoid leaking by
125 // manually clearing the subtitles
126 if (!m_externalParser &&
128 {
129 LOG(VB_GENERAL, LOG_ERR,
130 QString("SubtitleReader: %1 AVSubtitles queued (more than %2) - clearing.")
131 .arg(m_avSubtitles.m_buffers.size())
133 clearsubs = true;
134 }
135 m_avSubtitles.m_lock.unlock();
136
137 if (clearsubs)
139
140 return enableforced;
141}
142
144{
145 m_avSubtitles.m_lock.lock();
146 while (!m_avSubtitles.m_buffers.empty())
147 {
149 m_avSubtitles.m_buffers.pop_front();
150 }
151 m_avSubtitles.m_lock.unlock();
152}
153
154void SubtitleReader::FreeAVSubtitle(AVSubtitle &subtitle)
155{
156 avsubtitle_free(&subtitle);
157}
158
159void SubtitleReader::LoadExternalSubtitles(const QString &subtitleFileName,
160 bool isInProgress)
161{
162 m_textSubtitles.SetInProgress(isInProgress);
163 if (!subtitleFileName.isEmpty())
164 {
165 m_externalParser = new TextSubtitleParser(this, subtitleFileName, &m_textSubtitles);
167 }
168}
169
171{
175 return -1;
176}
177
179{
181}
182
183QStringList SubtitleReader::GetRawTextSubtitles(std::chrono::milliseconds &duration)
184{
185 QMutexLocker lock(&m_rawTextSubtitles.m_lock);
186 if (m_rawTextSubtitles.m_buffers.empty())
187 return {};
188
190 QStringList result = m_rawTextSubtitles.m_buffers;
192 return result;
193}
194
195void SubtitleReader::AddRawTextSubtitle(const QStringList& list, std::chrono::milliseconds duration)
196{
197 if (!m_rawTextSubtitlesEnabled || list.empty())
198 return;
199
200 QMutexLocker lock(&m_rawTextSubtitles.m_lock);
204}
205
207{
208 QMutexLocker lock(&m_rawTextSubtitles.m_lock);
210}
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)
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