MythTV  master
videovisualmonoscope.cpp
Go to the documentation of this file.
1 // MythTV
4 #include "videovisualmonoscope.h"
5 
7  : VideoVisual(Audio, Render),
8  m_fade(Fade)
9 {
10 }
11 
13 {
14  auto *render = dynamic_cast<MythRenderOpenGL*>(m_render);
15  if (!render)
16  return;
17 
18  OpenGLLocker locker(render);
19  render->DeleteShaderProgram(m_shader);
20  delete m_vbo;
21  delete m_fbo[0];
22  delete m_fbo[1];
23  render->DeleteTexture(m_texture[0]);
24  render->DeleteTexture(m_texture[1]);
25 }
26 
28 {
29  return m_fade ? "FadeScope" : "SimpleScope";
30 }
31 
33 {
34  auto *render = dynamic_cast<MythRenderOpenGL*>(m_render);
35  if (!render)
36  return nullptr;
37 
38  if (Area == m_area)
39  {
40  if (!m_fade && m_shader && m_vbo)
41  return render;
42  if (m_fade && m_shader && m_vbo && m_fbo[0] && m_fbo[1] && m_texture[0] && m_texture[1])
43  return render;
44  }
45 
46  OpenGLLocker locker(render);
47 
48  if (!m_shader)
49  m_shader = render->CreateShaderProgram(kSimpleVertexShader, kSimpleFragmentShader);
50  if (!m_vbo)
51  m_vbo = render->CreateVBO(NUM_SAMPLES * 2 * sizeof(GLfloat), false);
52 
53  m_hue = 0.0;
54  m_area = Area;
55  m_lastTime = QDateTime::currentMSecsSinceEpoch();
56 
57  delete m_fbo[0];
58  delete m_fbo[1];
59  render->DeleteTexture(m_texture[0]);
60  render->DeleteTexture(m_texture[1]);
61  m_fbo[0] = nullptr;
62  m_fbo[1] = nullptr;
63  m_texture[0] = nullptr;
64  m_texture[1] = nullptr;
65  m_currentFBO = false;
66 
67  if (m_fade)
68  {
69 
70  QSize size(m_area.size());
71  m_fbo[0] = render->CreateFramebuffer(size);
72  m_fbo[1] = render->CreateFramebuffer(size);
73  render->SetBackground(0, 0, 0, 255);
74  render->SetViewPort(m_area);
75  if (m_fbo[0])
76  {
77  m_texture[0] = render->CreateFramebufferTexture(m_fbo[0]);
78  render->BindFramebuffer(m_fbo[0]);
79  render->ClearFramebuffer();
80  }
81  if (m_fbo[1])
82  {
83  m_texture[1] = render->CreateFramebufferTexture(m_fbo[1]);
84  render->BindFramebuffer(m_fbo[1]);
85  render->ClearFramebuffer();
86  }
87  if (m_texture[0])
88  render->SetTextureFilters(m_texture[0], QOpenGLTexture::Linear);
89  if (m_texture[1])
90  render->SetTextureFilters(m_texture[1], QOpenGLTexture::Linear);
91  return (m_shader && m_vbo && m_fbo[0] && m_fbo[1] &&
92  m_texture[0] && m_texture[1]) ? render : nullptr;
93  }
94 
95  if (m_shader && m_vbo)
96  return render;
97  return nullptr;
98 }
99 
100 void VideoVisualMonoScope::Draw(const QRect &Area, MythPainter* /*painter*/, QPaintDevice* /*device*/)
101 {
102  if (m_disabled)
103  return;
104 
105  VisualNode *node = nullptr;
106  MythRenderOpenGL *render = nullptr;
107 
108  {
109  QMutexLocker locker(mutex());
110  node = GetNode();
111 
112  if (Area.isEmpty() || !node)
113  return;
114  if (!(render = Initialise(Area)))
115  return;
116 
117  int y = m_area.height() / 2;
118  int x = 0;
119  int xstep = m_area.width() / NUM_SAMPLES + 1;
120 
121  double index = 0;
122  double const step = static_cast<double>(node->m_length) / NUM_SAMPLES;
123  for ( int i = 0; i < NUM_SAMPLES; i++)
124  {
125  auto indexTo = static_cast<long>(index + step);
126  if (indexTo == static_cast<long>(index))
127  indexTo = static_cast<long>(index + 1);
128 
129  double value = 0.0;
130  for (auto s = static_cast<long>(index); s < indexTo && s < node->m_length; s++)
131  {
132  double temp = (static_cast<double>(node->m_left[s]) +
133  (node->m_right ? static_cast<double>(node->m_right[s]) : 0.0) *
134  (static_cast<double>(m_area.height())) ) / 65536.0;
135  value = temp > 0.0 ? qMax(temp, value) : qMin(temp, value);
136  }
137 
138  index += step;
139  m_vertices[i * 2] = x;
140  m_vertices[i * 2 + 1] = y + static_cast<GLfloat>(value);
141  x += xstep;
142  }
143  }
144 
145  // try and give a similar rate of transitions for different playback speeds
146  qint64 timenow = QDateTime::currentMSecsSinceEpoch();
147  qreal rate = (timenow - m_lastTime);
148  m_lastTime = timenow;
149 
150  render->makeCurrent();
151 
152  int lastfbo = static_cast<int>(m_currentFBO);
153  int nextfbo = static_cast<int>(!m_currentFBO);
154 
155  if (m_fade)
156  {
157  // bind the next framebuffer
158  render->BindFramebuffer(m_fbo[nextfbo]);
159  // Clear
160  render->SetBackground(0, 0, 0, 255);
161  render->SetViewPort(m_area);
162  render->ClearFramebuffer();
163  // Zoom out a little
164  qreal zoom = 1.0 - (rate / 4000.0);
165  int width = static_cast<int>(m_area.width() * zoom);
166  int height = static_cast<int>(m_area.height() * zoom);
167  QRect dest = QRect((m_area.width() - width) / 2, (m_area.height() - height) / 2,
168  width, height);
169  // render last framebuffer into next with a little alpha fade
170  // N.B. this alpha fade, in conjunction with the clear alpha above, causes
171  // us to grey out the underlying video (if rendered over video).
172  render->DrawBitmap(m_texture[lastfbo], m_fbo[nextfbo], m_area, dest,
173  nullptr, static_cast<int>(255.0 - rate / 2));
174  }
175 
176  // Draw the scope - either to screen or to our framebuffer object
177  QColor color = QColor::fromHsvF(m_hue, 1.0, 1.0);
178  m_hue += rate / 7200.0;
179  if (m_hue > 1.0)
180  m_hue -= 1.0;
181  render->glEnableVertexAttribArray(0);
182  m_vbo->bind();
183  m_vbo->write(0, m_vertices, NUM_SAMPLES * 2 * sizeof(GLfloat));
184  render->glVertexAttrib4f(1, static_cast<GLfloat>(color.redF()),
185  static_cast<GLfloat>(color.greenF()),
186  static_cast<GLfloat>(color.blueF()), 1.0F);
187  render->SetShaderProjection(m_shader);
188  render->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
189  render->glLineWidth(static_cast<int>(m_area.height() * 0.004F));
190  render->glDrawArrays(GL_LINE_STRIP, 0, NUM_SAMPLES);
191  render->glLineWidth(1);
192  QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
193  render->glDisableVertexAttribArray(0);
194 
195  // Render and swap buffers
196  if (m_fade)
197  {
198  render->DrawBitmap(m_texture[nextfbo], nullptr, m_area, m_area, nullptr);
200  }
201 
202  render->doneCurrent();
203 }
204 
206 {
207  public:
208  const QString &name(void) const override
209  {
210  static QString s_name("FadeScope");
211  return s_name;
212  }
213 
214  VideoVisual *Create(AudioPlayer *Audio, MythRender *Render) const override
215  {
216  return new VideoVisualMonoScope(Audio, Render, true);
217  }
218 
220  {
221  return (type == kRenderOpenGL);
222  }
224 
226 {
227  public:
228  const QString &name(void) const override
229  {
230  static QString s_name("SimpleScope");
231  return s_name;
232  }
233 
234  VideoVisual *Create(AudioPlayer *Audio, MythRender *Render) const override
235  {
236  return new VideoVisualMonoScope(Audio, Render, false);
237  }
238 
240  {
241  return (type == kRenderOpenGL);
242  }
bool SupportedRenderer(RenderType type) override
VideoVisualMonoScope(AudioPlayer *Audio, MythRender *Render, bool Fade)
VisualNode * GetNode(void)
Definition: videovisual.cpp:88
#define NUM_SAMPLES
QOpenGLFramebufferObject * m_fbo[2]
const QString & name(void) const override
void SetBackground(int Red, int Green, int Blue, int Alpha)
void SetViewPort(const QRect &Rect, bool ViewportOnly=false)
void BindFramebuffer(QOpenGLFramebufferObject *Framebuffer)
VideoVisual * Create(AudioPlayer *Audio, MythRender *Render) const override
const QString & name(void) const override
void Draw(const QRect &Area, MythPainter *Painter, QPaintDevice *) override
bool m_disabled
Definition: videovisual.h:64
VideoVisualSimpleScopeFactory VideoVisualSimpleScopeFactory
short * m_right
Definition: videovisual.h:35
QString Name(void) override
VideoVisualMonoScopeFactory VideoVisualMonoScopeFactory
void SetShaderProjection(QOpenGLShaderProgram *Program)
GLfloat m_vertices[(NUM_SAMPLES *2)+16]
MythRenderOpenGL * Initialise(const QRect &Area)
bool SupportedRenderer(RenderType type) override
void DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, const QRect &Source, const QRect &Destination, QOpenGLShaderProgram *Program, int Alpha=255)
static const QString kSimpleVertexShader
MythGLTexture * m_texture[2]
static const QString kSimpleFragmentShader
long m_length
Definition: videovisual.h:36
QMutex * mutex()
Definition: visual.h:25
VideoVisual * Create(AudioPlayer *Audio, MythRender *Render) const override
QOpenGLShaderProgram * m_shader
RenderType
MythRender * m_render
Definition: videovisual.h:66
QRect m_area
Definition: videovisual.h:65
short * m_left
Definition: videovisual.h:34
void ClearFramebuffer(void)