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