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