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