MythTV master
videovisual.cpp
Go to the documentation of this file.
1#include <algorithm>
2
5#include "mythplayer.h"
6#include "videovisual.h"
7
9
11{
12 QStringList result;
13 for (auto *factory = VideoVisualFactory::VideoVisualFactories();
14 factory; factory = factory->next())
15 {
16 if (factory->SupportedRenderer(type))
17 result << factory->name();
18 }
19 result.sort();
20 return result;
21}
22
23VideoVisual* VideoVisual::Create(const QString &name,
24 AudioPlayer *audio, MythRender *render)
25{
26 if (!audio || !render || name.isEmpty())
27 return nullptr;
28
29 for (auto *factory = VideoVisualFactory::VideoVisualFactories();
30 factory; factory = factory->next())
31 {
32 if (name.isEmpty())
33 return factory->Create(audio, render);
34 if (factory->name() == name)
35 return factory->Create(audio, render);
36 }
37 return nullptr;
38}
39
41 : m_audio(audio),
42 m_render(render),
43 m_lastUpdate(QDateTime::currentDateTimeUtc())
44{
45 mutex()->lock();
46 if (m_audio)
47 m_audio->addVisual(this);
48 mutex()->unlock();
49}
50
52{
53 mutex()->lock();
54 if (m_audio)
55 m_audio->removeVisual(this);
57 mutex()->unlock();
58}
59
60std::chrono::milliseconds VideoVisual::SetLastUpdate(void)
61{
62 QDateTime now = QDateTime::currentDateTimeUtc();
63 auto result = std::chrono::milliseconds(m_lastUpdate.time().msecsTo(now.time()));
64 m_lastUpdate = now;
65 return result;
66}
67
68// caller holds lock
70{
71 while (!m_nodes.empty())
72 {
73 delete m_nodes.back();
74 m_nodes.pop_back();
75 }
76}
77
78// caller holds lock
80{
82}
83
84// caller holds lock
86{
87 std::chrono::milliseconds timestamp = m_audio->GetAudioTime();
88 while (m_nodes.size() > 1)
89 {
90 if (m_nodes.front()->m_offset > timestamp)
91 break;
92 delete m_nodes.front();
93 m_nodes.pop_front();
94 }
95
96 if (m_nodes.isEmpty())
97 return nullptr;
98
99 return m_nodes.first();
100}
101
102// TODO Add MMX path
104 short *l, short *r, const float *s, unsigned long cnt)
105{
106 const float f((1 << 15) - 1);
107 while (cnt--)
108 {
109 *l++ = short(f * *s++);
110 *r++ = short(f * *s++);
111 }
112}
113
114// TODO Add MMX path
115static inline void mono16_from_monofloat32(
116 short *l, const float *s, unsigned long cnt)
117{
118 const float f((1 << 15) - 1);
119 while (cnt--)
120 *l++ = short(f * *s++);
121}
122
123// caller holds lock
124void VideoVisual::add(const void *b, unsigned long b_len,
125 std::chrono::milliseconds timecode,
126 int c, int p)
127{
128 if (!m_disabled && m_nodes.size() > 500)
129 {
130 LOG(VB_GENERAL, LOG_ERR, DESC +
131 QString("Over 500 nodes buffered - disabling visualiser."));
132 DeleteNodes();
133 m_disabled = true;
134 }
135
136 if (m_disabled)
137 return;
138
139 long len = b_len;
140 short *l = nullptr;
141 short *r = nullptr;
142
143 len /= c;
144 len /= (p / 8);
145
146 len = std::min<long>(len, 512);
147
148 long cnt = len;
149
150 if (c == 2)
151 {
152 l = new short[len];
153 r = new short[len];
154
155 if (p == 8)
156 stereo16_from_stereopcm8(l, r, (uchar *) b, cnt);
157 else if (p == 16)
158 stereo16_from_stereopcm16(l, r, (short *) b, cnt);
159 else if (p == 32)
160 stereo16_from_stereofloat32(l, r, reinterpret_cast<const float * >(b), cnt);
161 else
162 len = 0;
163 }
164 else if (c == 1)
165 {
166 l = new short[len];
167
168 if (p == 8)
169 mono16_from_monopcm8(l, (uchar *) b, cnt);
170 else if (p == 16)
171 mono16_from_monopcm16(l, (short *) b, cnt);
172 else if (p == 32)
173 mono16_from_monofloat32(l, reinterpret_cast<const float * >(b), cnt);
174 else
175 len = 0;
176 }
177 else
178 {
179 len = 0;
180 }
181
182 m_nodes.append(new VisualNode(l, r, len, timecode));
183}
std::chrono::milliseconds GetAudioTime(void)
void addVisual(MythTV::Visual *vis)
Definition: audioplayer.cpp:28
void removeVisual(MythTV::Visual *vis)
Definition: audioplayer.cpp:42
QMutex * mutex()
Definition: visual.h:26
VideoVisualFactory * next() const
Definition: videovisual.h:93
static VideoVisualFactory * VideoVisualFactories()
Definition: videovisual.h:89
static VideoVisualFactory * g_videoVisualFactory
Definition: videovisual.h:100
QDateTime m_lastUpdate
Definition: videovisual.h:74
AudioPlayer * m_audio
Definition: videovisual.h:68
VisualNode * GetNode(void)
Definition: videovisual.cpp:85
void prepare() override
Definition: videovisual.cpp:79
~VideoVisual() override
Definition: videovisual.cpp:51
bool m_disabled
Definition: videovisual.h:70
VideoVisual(AudioPlayer *audio, MythRender *render)
Definition: videovisual.cpp:40
QList< VisualNode * > m_nodes
Definition: videovisual.h:73
std::chrono::milliseconds SetLastUpdate(void)
Definition: videovisual.cpp:60
static VideoVisual * Create(const QString &name, AudioPlayer *audio, MythRender *render)
Definition: videovisual.cpp:23
void add(const void *b, unsigned long b_len, std::chrono::milliseconds timecode, int c, int p) override
static QStringList GetVisualiserList(RenderType type)
Definition: videovisual.cpp:10
void DeleteNodes(void)
Definition: videovisual.cpp:69
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
RenderType
static void mono16_from_monofloat32(short *l, const float *s, unsigned long cnt)
static void stereo16_from_stereofloat32(short *l, short *r, const float *s, unsigned long cnt)
#define DESC
Definition: videovisual.h:19
static void mono16_from_monopcm16(short *l, const short *s, long cnt)
static void mono16_from_monopcm8(short *l, const uchar *c, long cnt)
static void stereo16_from_stereopcm8(short *l, short *r, const uchar *c, long cnt)
static void stereo16_from_stereopcm16(short *l, short *r, const short *s, long cnt)