MythTV  master
mythtv/programs/mythavtest/main.cpp
Go to the documentation of this file.
1 #include <unistd.h>
2 #include <iostream>
3 
4 using namespace std;
5 
6 #include <QString>
7 #include <QRegExp>
8 #include <QDir>
9 #include <QApplication>
10 #include <QTime>
11 
12 #include "tv_play.h"
13 #include "programinfo.h"
14 #include "commandlineparser.h"
15 #include "mythplayer.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 "videooutbase.h"
28 
29 // libmythui
30 #include "mythuihelper.h"
31 #include "mythmainwindow.h"
32 
34 {
35  public:
36  VideoPerformanceTest(const QString &filename, bool novsync, bool onlydecode,
37  int runfor, bool deint, bool gpu)
38  : file(filename), novideosync(novsync), decodeonly(onlydecode),
39  secondstorun(runfor), deinterlace(deint), allowgpu(gpu), ctx(nullptr)
40  {
41  if (secondstorun < 1)
42  secondstorun = 1;
43  if (secondstorun > 3600)
44  secondstorun = 3600;
45  }
46 
48  {
49  delete ctx;
50  }
51 
52  void Test(void)
53  {
54  PIPMap dummy;
55 
56  if (novideosync) // TODO
57  LOG(VB_GENERAL, LOG_INFO, "Will attempt to disable sync-to-vblank.");
58 
59  RingBuffer *rb = RingBuffer::Create(file, false, true, 2000);
61  mp->GetAudio()->SetAudioInfo("NULL", "NULL", 0, 0);
62  mp->GetAudio()->SetNoAudio();
63  ctx = new PlayerContext("VideoPerformanceTest");
64  ctx->SetRingBuffer(rb);
65  ctx->SetPlayer(mp);
66  ctx->SetPlayingInfo(new ProgramInfo(file));
67  mp->SetPlayerInfo(nullptr, GetMythMainWindow(), ctx);
68 
70  if (!mp->StartPlaying())
71  {
72  LOG(VB_GENERAL, LOG_ERR, "Failed to start playback.");
73  return;
74  }
75 
76  VideoOutput *vo = mp->GetVideoOutput();
77  if (!vo)
78  {
79  LOG(VB_GENERAL, LOG_ERR, "No video output.");
80  return;
81  }
82 
83  LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
84  LOG(VB_GENERAL, LOG_INFO, "Ensure Sync to VBlank is disabled.");
85  LOG(VB_GENERAL, LOG_INFO, "Otherwise rate will be limited to that of the display.");
86  LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
87  LOG(VB_GENERAL, LOG_INFO, QString("Starting video performance test for '%1'.")
88  .arg(file));
89  LOG(VB_GENERAL, LOG_INFO, QString("Test will run for %1 seconds.")
90  .arg(secondstorun));
91 
92  if (decodeonly)
93  LOG(VB_GENERAL, LOG_INFO, "Decoding frames only - skipping display.");
94 
95  bool doublerate = vo->NeedsDoubleFramerate();
96  if (deinterlace)
97  {
98  LOG(VB_GENERAL, LOG_INFO, QString("Deinterlacing: %1")
99  .arg(doublerate ? "doublerate" : "singlerate"));
100  if (doublerate)
101  LOG(VB_GENERAL, LOG_INFO, "Output will show fields per second");
102  }
103  else
104  {
105  LOG(VB_GENERAL, LOG_INFO, "Deinterlacing disabled");
106  }
107 
108  DecoderBase* dec = mp->GetDecoder();
109  if (dec)
110  LOG(VB_GENERAL, LOG_INFO, QString("Using decoder: %1").arg(dec->GetCodecDecoderName()));
111 
112  Jitterometer *jitter = new Jitterometer("Performance: ", mp->GetFrameRate() * (doublerate ? 2 : 1));
113 
114  int ms = secondstorun * 1000;
115  QTime start = QTime::currentTime();
116  while (true)
117  {
118  int duration = start.msecsTo(QTime::currentTime());
119  if (duration < 0 || duration > ms)
120  {
121  LOG(VB_GENERAL, LOG_INFO, "Complete.");
122  break;
123  }
124 
125  if (mp->IsErrored())
126  {
127  LOG(VB_GENERAL, LOG_ERR, "Playback error.");
128  break;
129  }
130 
131  if (mp->GetEof() != kEofStateNone)
132  {
133  LOG(VB_GENERAL, LOG_INFO, "End of file.");
134  break;
135  }
136 
137  if (!mp->PrebufferEnoughFrames())
138  continue;
139 
140  mp->SetBuffering(false);
141  vo->StartDisplayingFrame();
142  VideoFrame *frame = vo->GetLastShownFrame();
143  mp->CheckAspectRatio(frame);
144 
145  if (!decodeonly)
146  {
147  vo->ProcessFrame(frame, nullptr, nullptr, dummy, scan);
148  vo->PrepareFrame(frame, scan, nullptr);
149  vo->Show(scan);
150 
151  if (vo->NeedsDoubleFramerate() && deinterlace)
152  {
153  vo->PrepareFrame(frame, kScan_Intr2ndField, nullptr);
154  vo->Show(scan);
155  }
156  }
157  vo->DoneDisplayingFrame(frame);
158  jitter->RecordCycleTime();
159  }
160  LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
161  delete jitter;
162  }
163 
164  private:
165  QString file;
170  bool allowgpu;
172 };
173 
174 int main(int argc, char *argv[])
175 {
176 
177 #if CONFIG_OMX_RPI
178  setenv("QT_XCB_GL_INTEGRATION","none",0);
179 #endif
180 
181  // try and disable sync to vblank on linux x11
182  qputenv("vblank_mode", "0"); // Intel and AMD
183  qputenv("__GL_SYNC_TO_VBLANK", "0"); // NVidia
184 
186  if (!cmdline.Parse(argc, argv))
187  {
188  cmdline.PrintHelp();
190  }
191 
192  if (cmdline.toBool("showhelp"))
193  {
194  cmdline.PrintHelp();
195  return GENERIC_EXIT_OK;
196  }
197 
198  if (cmdline.toBool("showversion"))
199  {
201  return GENERIC_EXIT_OK;
202  }
203 
204  QApplication a(argc, argv);
205  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHAVTEST);
206 
207  int retval;
208  if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
209  return retval;
210 
211  if (!cmdline.toString("display").isEmpty())
212  {
214  }
215 
216  if (!cmdline.toString("geometry").isEmpty())
217  {
219  }
220 
221  QString filename = "";
222  if (!cmdline.toString("infile").isEmpty())
223  filename = cmdline.toString("infile");
224  else if (cmdline.GetArgs().size() >= 1)
225  filename = cmdline.GetArgs()[0];
226 
228  if (!gContext->Init())
229  {
230  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
232  }
233 
235 
236  QString themename = gCoreContext->GetSetting("Theme");
237  QString themedir = GetMythUI()->FindThemeDir(themename);
238  if (themedir.isEmpty())
239  {
240  QString msg = QString("Fatal Error: Couldn't find theme '%1'.")
241  .arg(themename);
242  LOG(VB_GENERAL, LOG_ERR, msg);
243  return GENERIC_EXIT_NO_THEME;
244  }
245 
246  GetMythUI()->LoadQtConfig();
247 
248 #if defined(Q_OS_MACX)
249  // Mac OS X doesn't define the AudioOutputDevice setting
250 #else
251  QString auddevice = gCoreContext->GetSetting("AudioOutputDevice");
252  if (auddevice.isEmpty())
253  {
254  LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Audio not configured, you need "
255  "to run 'mythfrontend', not 'mythtv'.");
257  }
258 #endif
259 
260  MythMainWindow *mainWindow = GetMythMainWindow();
261 #if CONFIG_DARWIN
262  mainWindow->Init(OPENGL2_PAINTER);
263 #else
264  mainWindow->Init();
265 #endif
266 
267 #ifndef _WIN32
268  QList<int> signallist;
269  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
270  << SIGILL;
271 #if ! CONFIG_DARWIN
272  signallist << SIGRTMIN;
273 #endif
274  SignalHandler::Init(signallist);
275  signal(SIGHUP, SIG_IGN);
276 #endif
277 
278  if (cmdline.toBool("test"))
279  {
280  int seconds = 5;
281  if (!cmdline.toString("seconds").isEmpty())
282  seconds = cmdline.toInt("seconds");
283  VideoPerformanceTest *test = new VideoPerformanceTest(filename, false,
284  cmdline.toBool("decodeonly"), seconds,
285  cmdline.toBool("deinterlace"),
286  cmdline.toBool("gpu"));
287  test->Test();
288  delete test;
289  }
290  else
291  {
292  TV::InitKeys();
293  setHttpProxy();
294 
295  if (!UpgradeTVDatabaseSchema(false))
296  {
297  LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Incorrect database schema.");
298  delete gContext;
300  }
301 
302  if (filename.isEmpty())
303  {
304  TV::StartTV(nullptr, kStartTVNoFlags);
305  }
306  else
307  {
308  ProgramInfo pginfo(filename);
309  TV::StartTV(&pginfo, kStartTVNoFlags);
310  }
311  }
313 
314  delete gContext;
315 
317 
318  return GENERIC_EXIT_OK;
319 }
320 
321 /* vim: set expandtab tabstop=4 shiftwidth=4: */
Startup context for MythTV.
Definition: mythcontext.h:42
QString FindThemeDir(const QString &themename, bool doFallback=true)
Returns the full path to the theme denoted by themename.
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
def scan(profile, smoonURL, gate)
Definition: scan.py:43
static QString themedir
Definition: mythdirs.cpp:21
QMap< MythPlayer *, PIPLocation > PIPMap
Definition: videooutbase.h:37
PlayerFlags
Definition: mythplayer.h:88
void LoadQtConfig(void)
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
VideoOutput * GetVideoOutput(void)
Definition: mythplayer.h:244
void setHttpProxy(void)
Get network proxy settings from OS, and use for [Q]Http[Comms].
virtual bool NeedsDoubleFramerate(void) const
Should Prepare() and Show() be called twice for every ProcessFrame().
void SetAudioInfo(const QString &main_device, const QString &passthru_device, uint samplerate, int bitrate=-1)
Set audio output device parameters.
virtual bool StartPlaying(void)
void PrintHelp(void) const
Print command line option help.
static void Init(QList< int > &signallist, QObject *parent=nullptr)
virtual void PrepareFrame(VideoFrame *buffer, FrameScanType, OSD *osd)=0
void DestroyMythMainWindow(void)
void SetNoAudio(void)
Definition: audioplayer.h:51
FrameScanType
Definition: videoouttypes.h:80
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static RingBuffer * Create(const QString &xfilename, bool write, bool usereadahead=true, int timeout_ms=kDefaultOpenTimeout, bool stream_only=false)
Creates a RingBuffer instance.
Definition: ringbuffer.cpp:112
bool toBool(QString key) const
Returns stored QVariant as a boolean.
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:63
int main(int argc, char *argv[])
VideoPerformanceTest(const QString &filename, bool novsync, bool onlydecode, int runfor, bool deint, bool gpu)
static void SetX11Display(const QString &display)
This needs to be set before MythUIHelper is initialized so that the MythUIHelper::Init() can detect X...
#define OPENGL2_PAINTER
Definition: mythuidefines.h:4
virtual void StartDisplayingFrame(void)
Tell GetLastShownFrame() to return the next frame from the head of the queue of frames to display.
Definition: videooutbase.h:217
void ApplySettingsOverride(void)
Apply all overrides to the global context.
This class serves as the base class for all video output methods.
Definition: videooutbase.h:46
Holds information on recordings and videos.
Definition: programinfo.h:66
bool Init(const bool gui=true, const bool promptForBackend=false, const bool bypassAutoDiscovery=false, const bool ignoreDB=false)
QStringList GetArgs(void) const
Return list of additional values provided on the command line independent of any keyword.
AudioPlayer * GetAudio(void)
Definition: mythplayer.h:189
void Init(QString forcedpainter=QString(), bool mayReInit=true)
QString GetSetting(const QString &key, const QString &defaultval="")
float GetFrameRate(void) const
Definition: mythplayer.h:176
EofState GetEof(void) const
static void ParseGeometryOverride(const QString &geometry)
Parse an X11 style command line geometry string.
bool RecordCycleTime()
virtual void ProcessFrame(VideoFrame *frame, OSD *osd, FilterChain *filterList, const PIPMap &pipPlayers, FrameScanType scan=kScan_Ignore)=0
virtual QString GetCodecDecoderName(void) const =0
static void Done(void)
QString toString(QString key) const
Returns stored QVariant as a QString, falling to default if not provided.
bool IsErrored(void) const
MythCommFlagCommandLineParser cmdline
MythUIHelper * GetMythUI()
virtual void Show(FrameScanType)=0
MythMainWindow * GetMythMainWindow(void)
static bool StartTV(ProgramInfo *tvrec, uint flags, const ChannelInfoList &selection=ChannelInfoList())
returns true if the recording completed when exiting.
Definition: tv_play.cpp:330
virtual void DoneDisplayingFrame(VideoFrame *frame)
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
Definition: videooutbase.h:220
void SetPlayerInfo(TV *tv, QWidget *widget, PlayerContext *ctx)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define MYTH_APPNAME_MYTHAVTEST
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
virtual VideoFrame * GetLastShownFrame(void)
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
Definition: videooutbase.h:239
void SetBuffering(bool new_buffering)
#define SIGHUP
Definition: compat.h:206
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
Definition: exitcodes.h:21
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:16
virtual bool PrebufferEnoughFrames(int min_buffers=0)
int toInt(QString key) const
Returns stored QVariant as an integer, falling to default if not provided.
#define setenv(x, y, z)
Definition: compat.h:149
Implements a file/stream reader/writer.
#define GENERIC_EXIT_NO_THEME
No Theme available.
Definition: exitcodes.h:14
int ConfigureLogging(QString mask="general", unsigned int progress=0)
Read in logging options and initialize the logging interface.
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
static void InitKeys(void)
Definition: tv_play.cpp:547
void PrintVersion(void) const
Print application version information.
DecoderBase * GetDecoder(void)
Returns the stream decoder currently in use.
Definition: mythplayer.h:278
void CheckAspectRatio(VideoFrame *frame)
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16