00001 #include "mythrender_base.h"
00002 #include "mythplayer.h"
00003 #include "videovisual.h"
00004
00005 VideoVisualFactory* VideoVisualFactory::g_videoVisualFactory = NULL;
00006
00007 bool VideoVisual::CanVisualise(AudioPlayer *audio, MythRender *render)
00008 {
00009 if (!audio)
00010 return false;
00011 if (render && (audio->GetNumChannels() == 2 || audio->GetNumChannels() == 1))
00012 return true;
00013 return false;
00014 }
00015
00016 QStringList VideoVisual::GetVisualiserList(RenderType type)
00017 {
00018 QStringList result;
00019 VideoVisualFactory* factory;
00020 for (factory = VideoVisualFactory::VideoVisualFactories();
00021 factory; factory = factory->next())
00022 {
00023 if (factory->SupportedRenderer(type))
00024 result << factory->name();
00025 }
00026 result.sort();
00027 return result;
00028 }
00029
00030 VideoVisual* VideoVisual::Create(const QString &name,
00031 AudioPlayer *audio, MythRender *render)
00032 {
00033 if (!audio || !render || name.isEmpty())
00034 return NULL;
00035
00036 const VideoVisualFactory* factory;
00037 for (factory = VideoVisualFactory::VideoVisualFactories();
00038 factory; factory = factory->next())
00039 {
00040 if (name.isEmpty())
00041 return factory->Create(audio, render);
00042 else if (factory->name() == name)
00043 return factory->Create(audio, render);
00044 }
00045 return NULL;
00046 }
00047
00048 VideoVisual::VideoVisual(AudioPlayer *audio, MythRender *render)
00049 : m_audio(audio), m_disabled(false), m_area(QRect()), m_render(render)
00050 {
00051 m_lastUpdate = QDateTime::currentDateTime();
00052 mutex()->lock();
00053 if (m_audio)
00054 m_audio->addVisual(this);
00055 mutex()->unlock();
00056 }
00057
00058 VideoVisual::~VideoVisual()
00059 {
00060 mutex()->lock();
00061 if (m_audio)
00062 m_audio->removeVisual(this);
00063 DeleteNodes();
00064 mutex()->unlock();
00065 }
00066
00067 int64_t VideoVisual::SetLastUpdate(void)
00068 {
00069 QDateTime now = QDateTime::currentDateTime();
00070 int64_t result = m_lastUpdate.time().msecsTo(now.time());
00071 m_lastUpdate = now;
00072 return result;
00073 }
00074
00075
00076 void VideoVisual::DeleteNodes(void)
00077 {
00078 while (!m_nodes.empty())
00079 {
00080 delete m_nodes.back();
00081 m_nodes.pop_back();
00082 }
00083 }
00084
00085
00086 void VideoVisual::prepare()
00087 {
00088 DeleteNodes();
00089 }
00090
00091
00092 VisualNode* VideoVisual::GetNode(void)
00093 {
00094 int64_t timestamp = m_audio->GetAudioTime();
00095 while (m_nodes.size() > 1)
00096 {
00097 if (m_nodes.front()->offset > timestamp)
00098 break;
00099 delete m_nodes.front();
00100 m_nodes.pop_front();
00101 }
00102
00103 if (m_nodes.isEmpty())
00104 return NULL;
00105
00106 return m_nodes.first();
00107 }
00108
00109
00110 void VideoVisual::add(uchar *b, unsigned long b_len, unsigned long w, int c,
00111 int p)
00112 {
00113 if (!m_disabled && m_nodes.size() > 500)
00114 {
00115 LOG(VB_GENERAL, LOG_ERR, DESC +
00116 QString("Over 500 nodes buffered - disabling visualiser."));
00117 DeleteNodes();
00118 m_disabled = true;
00119 }
00120
00121 if (m_disabled)
00122 return;
00123
00124 long len = b_len, cnt;
00125 short *l = 0, *r = 0;
00126
00127 len /= c;
00128 len /= (p / 8);
00129
00130 if (len > 512)
00131 len = 512;
00132
00133 cnt = len;
00134
00135 if (c == 2)
00136 {
00137 l = new short[len];
00138 r = new short[len];
00139
00140 if (p == 8)
00141 stereo16_from_stereopcm8(l, r, b, cnt);
00142 else if (p == 16)
00143 stereo16_from_stereopcm16(l, r, (short *) b, cnt);
00144 }
00145 else if (c == 1)
00146 {
00147 l = new short[len];
00148
00149 if (p == 8)
00150 mono16_from_monopcm8(l, b, cnt);
00151 else if (p == 16)
00152 mono16_from_monopcm16(l, (short *) b, cnt);
00153 }
00154 else
00155 len = 0;
00156
00157 m_nodes.append(new VisualNode(l, r, len, w));
00158 }