Skip to content

Commit

Permalink
libmythtv: Enable visualisations.
Browse files Browse the repository at this point in the history
- libfftw3 support is required at compile time and MUST be forced with
--enable-libfftw3 (existing libfftw3 support in configure appears to be
a hangover from previous code, it isn't actually used for anything else)

- much of the code is taken from mythmusic.

- visualisations will only work with 2 track audio streams.

- the visualisation is rendered over any video (and Pip) but beneath the
OSD.

- 2 visualisations are currently available. The 'default' is a simple
implementation of Spectrum which uses libmythui rendering routines and
is available when using the VDPAU, OpenGL and Direct3D9 renderers(i.e.
those with accelerated, overlaid OSDs). Circles is available when using
OpenGL 2.0 (not currently enabled) and, while a little easier on the
eye, is more a proof of concept to ensure correct inheritance,
dependency checking etc is working. It doesn't actually rely on the
features available with the OpenGL 2.0 renderer - though drawing of
circles is accelerated with that renderer.

- there is no technical reason why either visualisation will not work
with software rendered OSDs (e.g. XVideo). The limitation is purely a
performance consideration.

- adds a new keybinding "TOGGLEVISUALISATION" which is unbound by
default, otherwise the visualisation can be toggled via the new entry in
the OSD menu or the http interface.

- it should be easy enough to port any other mythmusic visualisations,
though libvisual integration is more difficult (and may not be
possible). If additional visualisations are made available, I'll add a
mechanism to chose which to use.
  • Loading branch information
Mark Kendall committed Mar 22, 2011
1 parent 057f1a9 commit 8fe7f45
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 2 deletions.
12 changes: 11 additions & 1 deletion mythtv/libs/libmythtv/libmythtv.pro
Expand Up @@ -24,7 +24,7 @@ DEPENDPATH += ../libmyth ../libmyth/audio
DEPENDPATH += ../libmythbase ../libmythhdhomerun
DEPENDPATH += ../libmythdvdnav/
DEPENDPATH += ../libmythbluray/
DEPENDPATH += ./dvbdev ./mpeg ./iptv ./channelscan
DEPENDPATH += ./dvbdev ./mpeg ./iptv ./channelscan ./visualisations
DEPENDPATH += ../libmythlivemedia/BasicUsageEnvironment/include
DEPENDPATH += ../libmythlivemedia/BasicUsageEnvironment
DEPENDPATH += ../libmythlivemedia/groupsock/include
Expand Down Expand Up @@ -320,12 +320,22 @@ using_frontend {
HEADERS += videodisplayprofile.h mythcodecid.h
HEADERS += videoouttypes.h util-osd.h
HEADERS += videooutwindow.h videocolourspace.h
HEADERS += videovisual.h videovisualdefs.h
SOURCES += videooutbase.cpp videoout_null.cpp
SOURCES += videobuffers.cpp vsync.cpp
SOURCES += jitterometer.cpp yuv2rgb.cpp
SOURCES += videodisplayprofile.cpp mythcodecid.cpp
SOURCES += videooutwindow.cpp util-osd.cpp
SOURCES += videocolourspace.cpp
SOURCES += videovisual.cpp

using_libfftw3 {
DEFINES += FFTW3_SUPPORT
HEADERS += videovisualspectrum.h
SOURCES += videovisualspectrum.cpp
using_opengl: HEADERS += videovisualcircles.h
using_opengl: SOURCES += videovisualcircles.cpp
}

using_quartz_video: DEFINES += USING_QUARTZ_VIDEO
using_quartz_video: HEADERS += videoout_quartz.h
Expand Down
14 changes: 14 additions & 0 deletions mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -4637,6 +4637,20 @@ void MythPlayer::ToggleStudioLevels(void)
SetOSDMessage(msg, kOSDTimeout_Med);
}

bool MythPlayer::CanVisualise(void)
{
if (videoOutput)
return videoOutput->CanVisualise(&audio, NULL);
return false;
}

bool MythPlayer::ToggleVisualisation(void)
{
if (videoOutput)
return videoOutput->ToggleVisualisation(&audio);
return false;
}

void MythPlayer::SetOSDMessage(const QString &msg, OSDTimeout timeout)
{
QMutexLocker locker(&osdLock);
Expand Down
4 changes: 4 additions & 0 deletions mythtv/libs/libmythtv/mythplayer.h
Expand Up @@ -291,6 +291,10 @@ class MTV_PUBLIC MythPlayer
// Public picture controls
void ToggleStudioLevels(void);

// Visualisations
bool CanVisualise(void);
bool ToggleVisualisation(void);

void SaveTotalDuration(void);
void ResetTotalDuration(void);

Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/tv_actions.h
Expand Up @@ -60,4 +60,7 @@
#define ACTION_TOGGLEBACKGROUND "TOGGLEBACKGROUND"
#define ACTION_REVEAL "REVEAL"

/* Visualisations */
#define ACTION_TOGGLEVISUALISATION "TOGGLEVISUALISATION"

#endif // TV_ACTIONS_H
27 changes: 27 additions & 0 deletions mythtv/libs/libmythtv/tv_play.cpp
Expand Up @@ -752,6 +752,10 @@ void TV::InitKeys(void)
REG_KEY("Teletext Menu", ACTION_REVEAL, QT_TRANSLATE_NOOP("MythControls",
"Reveal hidden Text"), "F8");

/* Visualisations */
REG_KEY("TV Playback", ACTION_TOGGLEVISUALISATION,
QT_TRANSLATE_NOOP("MythControls", "Toggle audio visualisation"), "");

/*
keys already used:
Expand Down Expand Up @@ -4030,6 +4034,8 @@ bool TV::ToggleHandleAction(PlayerContext *ctx,
ToggleAdjustFill(ctx);
else if (has_action("TOGGLEAUDIOSYNC", actions))
ChangeAudioSync(ctx, 0); // just display
else if (has_action(ACTION_TOGGLEVISUALISATION, actions))
ToggleVisualisation(ctx);
else if (has_action("TOGGLEPICCONTROLS", actions))
DoTogglePictureAttribute(ctx, kAdjustingPicture_Playback);
else if (has_action(ACTION_TOGGLESTUDIOLEVELS, actions))
Expand Down Expand Up @@ -4075,6 +4081,18 @@ bool TV::ToggleHandleAction(PlayerContext *ctx,
return handled;
}

void TV::ToggleVisualisation(const PlayerContext *ctx)
{
ctx->LockDeletePlayer(__FILE__, __LINE__);
if (ctx->player && ctx->player->CanVisualise())
{
bool on = ctx->player->ToggleVisualisation();
SetOSDMessage(ctx, on ? tr("Visualisation On") :
tr("Visualisation Off"));
}
ctx->UnlockDeletePlayer(__FILE__, __LINE__);
}

bool TV::PxPHandleAction(PlayerContext *ctx, const QStringList &actions)
{
if (!IsPIPSupported(ctx) && !IsPBPSupported(ctx))
Expand Down Expand Up @@ -9411,6 +9429,8 @@ void TV::OSDDialogEvent(int result, QString text, QString action)
}
else if (action.left(15) == "TOGGLEAUDIOSYNC")
ChangeAudioSync(actx, 0);
else if (action == ACTION_TOGGLEVISUALISATION)
ToggleVisualisation(actx);
else if (action.left(11) == ACTION_TOGGLESLEEP)
{
ToggleSleepTimer(actx, action.left(13));
Expand Down Expand Up @@ -9674,9 +9694,11 @@ void TV::FillOSDMenuAudio(const PlayerContext *ctx, OSD *osd,
QStringList tracks;
uint curtrack = ~0;
bool avsync = true;
bool visual = false;
ctx->LockDeletePlayer(__FILE__, __LINE__);
if (ctx->player)
{
visual = ctx->player->CanVisualise();
tracks = ctx->player->GetTracks(kTrackTypeAudio);
if (!tracks.empty())
curtrack = (uint) ctx->player->GetTrack(kTrackTypeAudio);
Expand Down Expand Up @@ -9704,6 +9726,11 @@ void TV::FillOSDMenuAudio(const PlayerContext *ctx, OSD *osd,
"DIALOG_MENU_AUDIOTRACKS_0", true,
selected == "AUDIOTRACKS");
}
if (visual)
{
osd->DialogAddButton(tr("Toggle Visualisation"),
ACTION_TOGGLEVISUALISATION);
}
if (avsync)
osd->DialogAddButton(tr("Adjust Audio Sync"), "TOGGLEAUDIOSYNC");
osd->DialogAddButton(tr("Toggle Audio Upmixer"), ACTION_TOGGLEUPMIX);
Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/tv_play.h
Expand Up @@ -618,6 +618,9 @@ class MTV_PUBLIC TV : public QObject
void DVDJumpForward(PlayerContext*);
bool DiscMenuHandleAction(PlayerContext*, const QStringList &actions);

// Visualisations
void ToggleVisualisation(const PlayerContext*);

// Program jumping stuff
void SetLastProgram(const ProgramInfo *rcinfo);
ProgramInfo *GetLastProgram(void) const;
Expand Down
4 changes: 4 additions & 0 deletions mythtv/libs/libmythtv/videoout_d3d.cpp
Expand Up @@ -369,6 +369,10 @@ void VideoOutputD3D::PrepareFrame(VideoFrame *buffer, FrameScanType t,
(*it)->Draw();
}
}

if (m_visual)
m_visual->Draw(GetTotalOSDBounds(), m_osd_painter, NULL);

if (osd && m_osd_painter && !window.IsEmbedding())
osd->DrawDirect(m_osd_painter, GetTotalOSDBounds().size(),
true);
Expand Down
5 changes: 5 additions & 0 deletions mythtv/libs/libmythtv/videoout_d3d.h
Expand Up @@ -58,6 +58,11 @@ class VideoOutputD3D : public VideoOutput
virtual bool ApproveDeintFilter(const QString& filtername) const;
void* GetDXVA2Decoder(void);

virtual bool CanVisualise(AudioPlayer *audio, MythRender *render)
{ return VideoOutput::CanVisualise(audio, m_render); }
virtual bool SetupVisualisation(AudioPlayer *audio, MythRender *render)
{ return VideoOutput::SetupVisualisation(audio, m_render); }

private:
void TearDown(void);
bool SetupContext(void);
Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/videoout_opengl.cpp
Expand Up @@ -443,6 +443,9 @@ void VideoOutputOpenGL::PrepareFrame(VideoFrame *buffer, FrameScanType t,
}
}

if (m_visual)
m_visual->Draw(GetTotalOSDBounds(), gl_painter, NULL);

if (osd && gl_painter && !window.IsEmbedding())
osd->DrawDirect(gl_painter, GetTotalOSDBounds().size(), true);

Expand Down
5 changes: 5 additions & 0 deletions mythtv/libs/libmythtv/videoout_opengl.h
Expand Up @@ -51,6 +51,11 @@ class VideoOutputOpenGL : public VideoOutput
virtual bool ApproveDeintFilter(const QString& filtername) const;
virtual MythPainter *GetOSDPainter(void) { return (MythPainter*)gl_painter; }

virtual bool CanVisualise(AudioPlayer *audio, MythRender *render)
{ return VideoOutput::CanVisualise(audio, gl_context); }
virtual bool SetupVisualisation(AudioPlayer *audio, MythRender *render)
{ return VideoOutput::SetupVisualisation(audio, gl_context); }

protected:
virtual bool CreateBuffers(void);
bool CreatePauseFrame(void);
Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/videoout_vdpau.cpp
Expand Up @@ -499,6 +499,9 @@ void VideoOutputVDPAU::PrepareFrame(VideoFrame *frame, FrameScanType scan,
m_pip_ready ? m_pip_layer : 0, 0))
VERBOSE(VB_PLAYBACK, LOC_ERR + QString("Prepare frame failed."));

if (m_visual)
m_visual->Draw(GetTotalOSDBounds(), m_osd_painter, NULL);

if (osd && m_osd_painter && !window.IsEmbedding())
osd->DrawDirect(m_osd_painter, GetTotalOSDBounds().size(), true);

Expand Down
5 changes: 5 additions & 0 deletions mythtv/libs/libmythtv/videoout_vdpau.h
Expand Up @@ -64,6 +64,11 @@ class VideoOutputVDPAU : public VideoOutput
void SetNextFrameDisplayTimeOffset(int delayus) { m_frame_delay = delayus; }
virtual MythPainter* GetOSDPainter(void) { return (MythPainter*)m_osd_painter; }

virtual bool CanVisualise(AudioPlayer *audio, MythRender *render)
{ return VideoOutput::CanVisualise(audio, m_render); }
virtual bool SetupVisualisation(AudioPlayer *audio, MythRender *render)
{ return VideoOutput::SetupVisualisation(audio, m_render); }

private:
virtual bool hasFullScreenOSD(void) const { return true; }
void TearDown(void);
Expand Down
39 changes: 38 additions & 1 deletion mythtv/libs/libmythtv/videooutbase.cpp
Expand Up @@ -342,8 +342,10 @@ VideoOutput::VideoOutput() :
monitor_sz(640,480), monitor_dim(400,300),

// OSD
osd_painter(NULL), osd_image(NULL)
osd_painter(NULL), osd_image(NULL),

// Visualisation
m_visual(NULL)
{
memset(&pip_tmp_image, 0, sizeof(pip_tmp_image));
db_display_dim = QSize(gCoreContext->GetNumSetting("DisplaySizeWidth", 0),
Expand Down Expand Up @@ -1292,6 +1294,13 @@ bool VideoOutput::DisplayOSD(VideoFrame *frame, OSD *osd)
return false;
}

if (m_visual)
{
VERBOSE(VB_IMPORTANT, LOC + "Visualiser not supported here");
// Clear the audio buffer
m_visual->Draw(QRect(), NULL, NULL);
}

QRegion dirty = QRegion();
QRegion visible = osd->Draw(osd_painter, osd_image, osd_size, dirty,
frame->codec == FMT_YV12 ? ALIGN_X_MMX : 0,
Expand Down Expand Up @@ -1340,6 +1349,34 @@ bool VideoOutput::DisplayOSD(VideoFrame *frame, OSD *osd)
return show;
}

bool VideoOutput::ToggleVisualisation(AudioPlayer *audio)
{
if (m_visual)
{
DestroyVisualisation();
return false;
}
return SetupVisualisation(audio, NULL);
}

bool VideoOutput::CanVisualise(AudioPlayer *audio, MythRender *render)
{
return VideoVisual::CanVisualise(audio, render);
}

bool VideoOutput::SetupVisualisation(AudioPlayer *audio, MythRender *render)
{
DestroyVisualisation();
m_visual = VideoVisual::Create(audio, render);
return m_visual;
}

void VideoOutput::DestroyVisualisation(void)
{
delete m_visual;
m_visual = NULL;
}

/**
* \fn VideoOutput::CopyFrame(VideoFrame*, const VideoFrame*)
* \brief Copies frame data from one VideoFrame to another.
Expand Down
13 changes: 13 additions & 0 deletions mythtv/libs/libmythtv/videooutbase.h
Expand Up @@ -23,6 +23,7 @@ extern "C" {
#include "DisplayRes.h"
#include "videodisplayprofile.h"
#include "videocolourspace.h"
#include "visualisations/videovisual.h"

using namespace std;

Expand All @@ -34,6 +35,8 @@ class OSD;
class FilterChain;
class FilterManager;
class OpenGLContextGLX;
class AudioPlayer;
class MythRender;

typedef QMap<MythPlayer*,PIPLocation> PIPMap;

Expand Down Expand Up @@ -243,6 +246,13 @@ class VideoOutput
QRect GetImageRect(const QRect &rect, QRect *display = NULL);
QRect GetSafeRect(void);

// Visualisations
bool ToggleVisualisation(AudioPlayer *audio);
virtual bool CanVisualise(AudioPlayer *audio, MythRender *render);
virtual bool SetupVisualisation(AudioPlayer *audio, MythRender *render);
void DestroyVisualisation(void);


protected:
void InitBuffers(int numdecode, bool extra_for_pause, int need_free,
int needprebuffer_normal, int needprebuffer_small,
Expand Down Expand Up @@ -323,6 +333,9 @@ class VideoOutput
// OSD painter and surface
MythYUVAPainter *osd_painter;
MythImage *osd_image;

// Visualisation
VideoVisual *m_visual;
};

#endif

0 comments on commit 8fe7f45

Please sign in to comment.