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