MythTV  master
mythtv/programs/mythavtest/main.cpp
Go to the documentation of this file.
1 #include <unistd.h>
2 #include <iostream>
3 #include <utility>
4 
5 #include <QApplication>
6 #include <QDir>
7 #include <QRegExp>
8 #include <QString>
9 #include <QSurfaceFormat>
10 #include <QTime>
11 
12 #include "tv_play.h"
13 #include "programinfo.h"
14 #include "commandlineparser.h"
15 #include "mythplayerui.h"
16 #include "jitterometer.h"
17 
18 #include "exitcodes.h"
19 #include "mythcontext.h"
20 #include "mythversion.h"
21 #include "mythdbcon.h"
22 #include "compat.h"
23 #include "dbcheck.h"
24 #include "mythlogging.h"
25 #include "signalhandling.h"
26 #include "mythmiscutil.h"
27 #include "mythvideoout.h"
28 
29 // libmythui
30 #include "mythuihelper.h"
31 #include "mythmainwindow.h"
32 
34 {
35  public:
36  VideoPerformanceTest(QString filename, bool decodeno, bool onlydecode,
37  int runfor, bool deint, bool gpu)
38  : m_file(std::move(filename)),
39  m_noDecode(decodeno),
40  m_decodeOnly(onlydecode),
41  m_secondsToRun(runfor),
42  m_deinterlace(deint),
43  m_allowGpu(gpu),
44  m_ctx(nullptr)
45  {
46  if (m_secondsToRun < 1)
47  m_secondsToRun = 1;
48  if (m_secondsToRun > 3600)
49  m_secondsToRun = 3600;
50  }
51 
53  {
54  delete m_ctx;
55  }
56 
57  void Test(void)
58  {
59  MythMediaBuffer *rb = MythMediaBuffer::Create(m_file, false, true, 2000);
60  m_ctx = new PlayerContext("VideoPerformanceTest");
61  auto *mp = new MythPlayerUI(GetMythMainWindow(), nullptr, m_ctx, static_cast<PlayerFlags>(kAudioMuted | (m_allowGpu ? kDecodeAllowGPU: kNoFlags)));
62  mp->GetAudio()->SetAudioInfo("NULL", "NULL", 0, 0);
63  mp->GetAudio()->SetNoAudio();
64  m_ctx->SetRingBuffer(rb);
65  m_ctx->SetPlayer(mp);
66  auto *pinfo = new ProgramInfo(m_file);
67  m_ctx->SetPlayingInfo(pinfo); // makes a copy
68  delete pinfo;
69 
71  if (!mp->StartPlaying())
72  {
73  LOG(VB_GENERAL, LOG_ERR, "Failed to start playback.");
74  return;
75  }
76 
77  MythVideoOutput *vo = mp->GetVideoOutput();
78  if (!vo)
79  {
80  LOG(VB_GENERAL, LOG_ERR, "No video output.");
81  return;
82  }
83 
84  LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
85  LOG(VB_GENERAL, LOG_INFO, "Ensure Sync to VBlank is disabled.");
86  LOG(VB_GENERAL, LOG_INFO, "Otherwise rate will be limited to that of the display.");
87  LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
88  LOG(VB_GENERAL, LOG_INFO, QString("Starting video performance test for '%1'.")
89  .arg(m_file));
90  LOG(VB_GENERAL, LOG_INFO, QString("Test will run for %1 seconds.")
92 
93  if (m_noDecode)
94  LOG(VB_GENERAL, LOG_INFO, "No decode after startup - checking display performance");
95  else if (m_decodeOnly)
96  LOG(VB_GENERAL, LOG_INFO, "Decoding frames only - skipping display.");
97  DecoderBase* dec = mp->GetDecoder();
98  if (dec)
99  LOG(VB_GENERAL, LOG_INFO, QString("Using decoder: %1").arg(dec->GetCodecDecoderName()));
100 
101  auto *jitter = new Jitterometer("Performance: ", static_cast<int>(mp->GetFrameRate()));
102 
103  int ms = m_secondsToRun * 1000;
104  QTime start = QTime::currentTime();
105  MythVideoFrame *frame = nullptr;
106  while (true)
107  {
108  mp->ProcessCallbacks();
109  int duration = start.msecsTo(QTime::currentTime());
110  if (duration < 0 || duration > ms)
111  {
112  LOG(VB_GENERAL, LOG_INFO, "Complete.");
113  break;
114  }
115 
116  if (mp->IsErrored())
117  {
118  LOG(VB_GENERAL, LOG_ERR, "Playback error.");
119  break;
120  }
121 
122  if (mp->GetEof() != kEofStateNone)
123  {
124  LOG(VB_GENERAL, LOG_INFO, "End of file.");
125  break;
126  }
127 
128  if (!mp->PrebufferEnoughFrames())
129  continue;
130 
131  mp->SetBuffering(false);
132  vo->StartDisplayingFrame();
133  if ((m_noDecode && !frame) || !m_noDecode)
134  frame = vo->GetLastShownFrame();
135  mp->CheckAspectRatio(frame);
136 
137  if (!m_decodeOnly)
138  {
140  vo->PrepareFrame(frame, scan);
141  vo->RenderFrame(frame, scan);
142  vo->EndFrame();
143 
144  if (doubledeint && m_deinterlace)
145  {
146  doubledeint = frame->GetDoubleRateOption(DEINT_CPU);
148  if (doubledeint && !other)
149  vo->PrepareFrame(frame, kScan_Intr2ndField);
150  vo->RenderFrame(frame, kScan_Intr2ndField);
151  vo->EndFrame();
152  }
153  }
154  if (!m_noDecode)
155  vo->DoneDisplayingFrame(frame);
156  jitter->RecordCycleTime();
157  }
158  LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
159  delete jitter;
160  }
161 
162  private:
163  QString m_file;
170 };
171 
172 int main(int argc, char *argv[])
173 {
175  if (!cmdline.Parse(argc, argv))
176  {
177  cmdline.PrintHelp();
179  }
180 
181  if (cmdline.toBool("showhelp"))
182  {
183  cmdline.PrintHelp();
184  return GENERIC_EXIT_OK;
185  }
186 
187  if (cmdline.toBool("showversion"))
188  {
190  return GENERIC_EXIT_OK;
191  }
192 
193  int swapinterval = 1;
194  if (cmdline.toBool("test"))
195  {
196  // try and disable sync to vblank on linux x11
197  qputenv("vblank_mode", "0"); // Intel and AMD
198  qputenv("__GL_SYNC_TO_VBLANK", "0"); // NVidia
199  // the default surface format has a swap interval of 1. This is used by
200  // the MythMainwindow widget that then drives vsync for all widgets/children
201  // (i.e. MythPainterWindow) and we cannot override it on some drivers. So
202  // force the default here.
203  swapinterval = 0;
204  }
205 
206  MythDisplay::ConfigureQtGUI(swapinterval, cmdline.toString("display"));
207 
208  QApplication a(argc, argv);
209  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHAVTEST);
210 
211  int retval = cmdline.ConfigureLogging();
212  if (retval != GENERIC_EXIT_OK)
213  return retval;
214 
215  if (!cmdline.toString("geometry").isEmpty())
217 
218  QString filename = "";
219  if (!cmdline.toString("infile").isEmpty())
220  filename = cmdline.toString("infile");
221  else if (!cmdline.GetArgs().empty())
222  filename = cmdline.GetArgs().at(0);
223 
225  if (!gContext->Init())
226  {
227  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
229  }
230 
232 
233  QString themename = gCoreContext->GetSetting("Theme");
234  QString themedir = GetMythUI()->FindThemeDir(themename);
235  if (themedir.isEmpty())
236  {
237  QString msg = QString("Fatal Error: Couldn't find theme '%1'.")
238  .arg(themename);
239  LOG(VB_GENERAL, LOG_ERR, msg);
240  return GENERIC_EXIT_NO_THEME;
241  }
242 
243 #if defined(Q_OS_MACX)
244  // Mac OS X doesn't define the AudioOutputDevice setting
245 #else
246  QString auddevice = gCoreContext->GetSetting("AudioOutputDevice");
247  if (auddevice.isEmpty())
248  {
249  LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Audio not configured, you need "
250  "to run 'mythfrontend', not 'mythtv'.");
252  }
253 #endif
254 
255  MythMainWindow *mainWindow = GetMythMainWindow();
256  mainWindow->Init();
257 
258 #ifndef _WIN32
259  QList<int> signallist;
260  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
261  << SIGILL;
262 #if ! CONFIG_DARWIN
263  signallist << SIGRTMIN;
264 #endif
265  SignalHandler::Init(signallist);
266  signal(SIGHUP, SIG_IGN);
267 #endif
268 
269  if (cmdline.toBool("test"))
270  {
271  int seconds = 5;
272  if (!cmdline.toString("seconds").isEmpty())
273  seconds = cmdline.toInt("seconds");
274  auto *test = new VideoPerformanceTest(filename,
275  cmdline.toBool("nodecode"),
276  cmdline.toBool("decodeonly"), seconds,
277  cmdline.toBool("deinterlace"),
278  cmdline.toBool("gpu"));
279  test->Test();
280  delete test;
281  }
282  else
283  {
284  TV::InitKeys();
285  setHttpProxy();
286 
287  if (!UpgradeTVDatabaseSchema(false))
288  {
289  LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Incorrect database schema.");
290  delete gContext;
292  }
293 
294  if (filename.isEmpty())
295  {
296  TV::StartTV(nullptr, kStartTVNoFlags);
297  }
298  else
299  {
300  ProgramInfo pginfo(filename);
301  TV::StartTV(&pginfo, kStartTVNoFlags);
302  }
303  }
305 
306  delete gContext;
307 
309 
310  return GENERIC_EXIT_OK;
311 }
312 
313 /* vim: set expandtab tabstop=4 shiftwidth=4: */
themedir
static QString themedir
Definition: mythdirs.cpp:21
TV::InitKeys
static void InitKeys()
Definition: tv_play.cpp:526
commandlineparser.h
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:70
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
MythVideoFrame::GetDoubleRateOption
MythDeintType GetDoubleRateOption(MythDeintType Type, MythDeintType Override=DEINT_NONE) const
Definition: mythframe.cpp:434
setHttpProxy
void setHttpProxy(void)
Get network proxy settings from OS, and use for [Q]Http[Comms].
Definition: mythmiscutil.cpp:848
MythUIScreenBounds::ParseGeometryOverride
static void ParseGeometryOverride(const QString &Geometry)
Parse an X11 style command line geometry string.
Definition: mythuiscreenbounds.cpp:38
MythVideoOutput
Definition: mythvideoout.h:31
mythvideoout.h
mythplayerui.h
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:69
kEofStateNone
@ kEofStateNone
Definition: decoderbase.h:69
PlayerContext::SetPlayingInfo
void SetPlayingInfo(const ProgramInfo *info)
assign programinfo to the context
Definition: playercontext.cpp:566
UpgradeTVDatabaseSchema
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
Definition: dbcheck.cpp:361
VideoPerformanceTest::VideoPerformanceTest
VideoPerformanceTest(QString filename, bool decodeno, bool onlydecode, int runfor, bool deint, bool gpu)
Definition: mythtv/programs/mythavtest/main.cpp:36
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, int Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:100
MythContext
Startup context for MythTV.
Definition: mythcontext.h:43
MythAVTestCommandLineParser
Definition: mythavtest/commandlineparser.h:7
MythVideoOutput::PrepareFrame
virtual void PrepareFrame(MythVideoFrame *Frame, FrameScanType Scan=kScan_Ignore)=0
arg
arg(title).arg(filename).arg(doDelete))
mythdbcon.h
FrameScanType
FrameScanType
Definition: videoouttypes.h:61
VideoPerformanceTest::m_ctx
PlayerContext * m_ctx
Definition: mythtv/programs/mythavtest/main.cpp:169
MythMediaBuffer
Definition: mythmediabuffer.h:50
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
PlayerFlags
PlayerFlags
Definition: mythplayer.h:79
GENERIC_EXIT_INVALID_CMDLINE
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
VideoPerformanceTest::m_noDecode
bool m_noDecode
Definition: mythtv/programs/mythavtest/main.cpp:164
hardwareprofile.scan.scan
def scan(profile, smoonURL, gate)
Definition: scan.py:57
TV::StartTV
static bool StartTV(ProgramInfo *TVRec, uint Flags, const ChannelInfoList &Selection=ChannelInfoList())
Start playback of media.
Definition: tv_play.cpp:323
mythversion.h
main
int main(int argc, char *argv[])
Definition: mythtv/programs/mythavtest/main.cpp:172
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:68
MythCommandLineParser::Parse
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
Definition: mythcommandlineparser.cpp:1437
MythPlayerUI
Definition: mythplayerui.h:12
MythVideoOutput::EndFrame
virtual void EndFrame()=0
DecoderBase::GetCodecDecoderName
virtual QString GetCodecDecoderName(void) const =0
kScan_Intr2ndField
@ kScan_Intr2ndField
Definition: videoouttypes.h:65
programinfo.h
mythlogging.h
kStartTVNoFlags
@ kStartTVNoFlags
Definition: tv_play.h:110
kScan_Progressive
@ kScan_Progressive
Definition: videoouttypes.h:66
dbcheck.h
signalhandling.h
VideoPerformanceTest::m_allowGpu
bool m_allowGpu
Definition: mythtv/programs/mythavtest/main.cpp:168
VideoPerformanceTest::Test
void Test(void)
Definition: mythtv/programs/mythavtest/main.cpp:57
compat.h
MythCommandLineParser::GetArgs
QStringList GetArgs(void) const
Return list of additional values provided on the command line independent of any keyword.
Definition: mythcommandlineparser.cpp:1832
GENERIC_EXIT_SETUP_ERROR
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
Definition: exitcodes.h:21
DestroyMythMainWindow
void DestroyMythMainWindow(void)
Definition: mythmainwindow.cpp:115
SIGHUP
#define SIGHUP
Definition: compat.h:214
MythUIThemeHelper::FindThemeDir
QString FindThemeDir(const QString &ThemeName, bool Fallback=true)
Returns the full path to the theme denoted by themename.
Definition: mythuithemehelper.cpp:47
kDecodeAllowGPU
@ kDecodeAllowGPU
Definition: mythplayer.h:86
MythCommandLineParser::PrintVersion
static void PrintVersion(void)
Print application version information.
Definition: mythcommandlineparser.cpp:1265
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
jitterometer.h
MythCommandLineParser::PrintHelp
void PrintHelp(void) const
Print command line option help.
Definition: mythcommandlineparser.cpp:1281
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
VideoPerformanceTest::m_file
QString m_file
Definition: mythtv/programs/mythavtest/main.cpp:163
MythCommandLineParser::ApplySettingsOverride
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Definition: mythcommandlineparser.cpp:2656
Jitterometer
Definition: jitterometer.h:44
MYTH_APPNAME_MYTHAVTEST
#define MYTH_APPNAME_MYTHAVTEST
Definition: mythcorecontext.h:30
MythVideoOutput::StartDisplayingFrame
virtual void StartDisplayingFrame()
Tell GetLastShownFrame() to return the next frame from the head of the queue of frames to display.
Definition: mythvideoout.cpp:504
mythuihelper.h
MYTH_BINARY_VERSION
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
MythDeintType
MythDeintType
Definition: mythframe.h:63
MythVideoOutput::RenderFrame
virtual void RenderFrame(MythVideoFrame *Frame, FrameScanType)=0
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythtv/programs/mythcommflag/main.cpp:76
kNoFlags
@ kNoFlags
Definition: mythplayer.h:80
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:68
mythmiscutil.h
MythCommandLineParser::toString
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2100
kScan_Interlaced
@ kScan_Interlaced
Definition: videoouttypes.h:64
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:1943
VideoPerformanceTest::m_deinterlace
bool m_deinterlace
Definition: mythtv/programs/mythavtest/main.cpp:167
PlayerContext::SetPlayer
void SetPlayer(MythPlayer *newplayer)
Definition: playercontext.cpp:511
PlayerContext::SetRingBuffer
void SetRingBuffer(MythMediaBuffer *Buffer)
Definition: playercontext.cpp:552
MythDisplay::ConfigureQtGUI
static void ConfigureQtGUI(int SwapInterval=1, const QString &Display=QString())
Shared static initialistaion code for all MythTV GUI applications.
Definition: mythdisplay.cpp:1039
mythcontext.h
GENERIC_EXIT_NO_MYTHCONTEXT
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
kAudioMuted
@ kAudioMuted
Definition: mythplayer.h:88
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:105
PlayerContext
Definition: playercontext.h:49
VideoPerformanceTest::m_secondsToRun
int m_secondsToRun
Definition: mythtv/programs/mythavtest/main.cpp:166
VideoPerformanceTest
Definition: mythtv/programs/mythavtest/main.cpp:34
VideoPerformanceTest::m_decodeOnly
bool m_decodeOnly
Definition: mythtv/programs/mythavtest/main.cpp:165
VideoPerformanceTest::~VideoPerformanceTest
~VideoPerformanceTest()
Definition: mythtv/programs/mythavtest/main.cpp:52
MythCommandLineParser::ConfigureLogging
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
Definition: mythcommandlineparser.cpp:2587
MythVideoFrame
Definition: mythframe.h:83
exitcodes.h
MythCommandLineParser::toInt
int toInt(const QString &key) const
Returns stored QVariant as an integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:1965
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:66
MythVideoOutput::GetLastShownFrame
virtual MythVideoFrame * GetLastShownFrame()
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
Definition: mythvideoout.cpp:405
mythmainwindow.h
GENERIC_EXIT_NO_THEME
#define GENERIC_EXIT_NO_THEME
No Theme available.
Definition: exitcodes.h:14
gContext
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:60
MythMainWindow::Init
void Init(bool mayReInit=true)
Definition: mythmainwindow.cpp:656
MythContext::Init
bool Init(bool gui=true, bool promptForBackend=false, bool disableAutoDiscovery=false, bool ignoreDB=false)
Definition: mythcontext.cpp:1560
MythMainWindow
Definition: mythmainwindow.h:35
SignalHandler::Done
static void Done(void)
Definition: signalhandling.cpp:131
DecoderBase
Definition: decoderbase.h:121
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:915
tv_play.h
MythVideoOutput::DoneDisplayingFrame
virtual void DoneDisplayingFrame(MythVideoFrame *Frame)
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
Definition: mythvideoout.cpp:511
SignalHandler::Init
static void Init(QList< int > &signallist, QObject *parent=nullptr)
Definition: signalhandling.cpp:124
GENERIC_EXIT_DB_OUTOFDATE
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16