MythTV  0.26-pre
main.cpp
Go to the documentation of this file.
00001 #include <unistd.h>
00002 #include <iostream>
00003 
00004 using namespace std;
00005 
00006 #include <QString>
00007 #include <QRegExp>
00008 #include <QDir>
00009 #include <QApplication>
00010 #include <QTime>
00011 
00012 #include "tv_play.h"
00013 #include "programinfo.h"
00014 #include "commandlineparser.h"
00015 #include "mythplayer.h"
00016 #include "jitterometer.h"
00017 
00018 #include "exitcodes.h"
00019 #include "mythcontext.h"
00020 #include "mythversion.h"
00021 #include "mythdbcon.h"
00022 #include "compat.h"
00023 #include "dbcheck.h"
00024 #include "mythlogging.h"
00025 
00026 // libmythui
00027 #include "mythuihelper.h"
00028 #include "mythmainwindow.h"
00029 
00030 class VideoPerformanceTest
00031 {
00032   public:
00033     VideoPerformanceTest(const QString &filename, bool novsync, bool onlydecode,
00034                          int runfor, bool deint)
00035       : file(filename), novideosync(novsync), decodeonly(onlydecode),
00036         secondstorun(runfor), deinterlace(deint), ctx(NULL)
00037     {
00038         if (secondstorun < 1)
00039             secondstorun = 1;
00040         if (secondstorun > 3600)
00041             secondstorun = 3600;
00042     }
00043 
00044    ~VideoPerformanceTest()
00045     {
00046         delete ctx;
00047     }
00048 
00049     void Test(void)
00050     {
00051         PIPMap dummy;
00052 
00053         if (novideosync) // TODO
00054             LOG(VB_GENERAL, LOG_INFO, "Will attempt to disable sync-to-vblank.");
00055 
00056         RingBuffer *rb  = RingBuffer::Create(file, false, true, 2000);
00057         MythPlayer  *mp  = new MythPlayer(kAudioMuted);
00058         mp->GetAudio()->SetAudioInfo("NULL", "NULL", 0, 0);
00059         mp->GetAudio()->SetNoAudio();
00060         ctx = new PlayerContext("VideoPerformanceTest");
00061         ctx->SetRingBuffer(rb);
00062         ctx->SetPlayer(mp);
00063         ctx->SetPlayingInfo(new ProgramInfo(file));
00064         mp->SetPlayerInfo(NULL, GetMythMainWindow(), ctx);
00065         FrameScanType scan = deinterlace ? kScan_Interlaced : kScan_Progressive;
00066         if (!mp->StartPlaying())
00067         {
00068             LOG(VB_GENERAL, LOG_ERR, "Failed to start playback.");
00069             return;
00070         }
00071 
00072         VideoOutput *vo = mp->GetVideoOutput();
00073         if (!vo)
00074         {
00075             LOG(VB_GENERAL, LOG_ERR, "No video output.");
00076             return;
00077         }
00078 
00079         LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
00080         LOG(VB_GENERAL, LOG_INFO, QString("Starting video performance test for '%1'.")
00081             .arg(file));
00082         LOG(VB_GENERAL, LOG_INFO, QString("Test will run for %1 seconds.")
00083             .arg(secondstorun));
00084 
00085         if (decodeonly)
00086             LOG(VB_GENERAL, LOG_INFO, "Decoding frames only - skipping display.");
00087         LOG(VB_GENERAL, LOG_INFO, QString("Deinterlacing %1")
00088             .arg(deinterlace ? "enabled" : "disabled"));
00089 
00090         Jitterometer *jitter = new Jitterometer("Performance: ", mp->GetFrameRate());
00091 
00092         int ms = secondstorun * 1000;
00093         QTime start = QTime::currentTime();
00094         while (1)
00095         {
00096             int duration = start.msecsTo(QTime::currentTime());
00097             if (duration < 0 || duration > ms)
00098             {
00099                 LOG(VB_GENERAL, LOG_INFO, "Complete.");
00100                 break;
00101             }
00102 
00103             if (mp->IsErrored())
00104             {
00105                 LOG(VB_GENERAL, LOG_ERR, "Playback error.");
00106                 break;
00107             }
00108 
00109             if (mp->GetEof())
00110             {
00111                 LOG(VB_GENERAL, LOG_INFO, "End of file.");
00112                 break;
00113             }
00114 
00115             if (!mp->PrebufferEnoughFrames())
00116                 continue;
00117 
00118             mp->SetBuffering(false);
00119             vo->StartDisplayingFrame();
00120             VideoFrame *frame = vo->GetLastShownFrame();
00121             mp->CheckAspectRatio(frame);
00122 
00123             if (!decodeonly)
00124             {
00125                 vo->ProcessFrame(frame, NULL, NULL, dummy, scan);
00126                 vo->PrepareFrame(frame, scan, NULL);
00127                 vo->Show(scan);
00128             }
00129             vo->DoneDisplayingFrame(frame);
00130             jitter->RecordCycleTime();
00131         }
00132         LOG(VB_GENERAL, LOG_INFO, "-----------------------------------");
00133     }
00134 
00135   private:
00136     QString file;
00137     bool    novideosync;
00138     bool    decodeonly;
00139     int     secondstorun;
00140     bool    deinterlace;
00141     PlayerContext *ctx;
00142 };
00143 
00144 int main(int argc, char *argv[])
00145 {
00146     MythAVTestCommandLineParser cmdline;
00147     if (!cmdline.Parse(argc, argv))
00148     {
00149         cmdline.PrintHelp();
00150         return GENERIC_EXIT_INVALID_CMDLINE;
00151     }
00152 
00153     if (cmdline.toBool("showhelp"))
00154     {
00155         cmdline.PrintHelp();
00156         return GENERIC_EXIT_OK;
00157     }
00158 
00159     if (cmdline.toBool("showversion"))
00160     {
00161         cmdline.PrintVersion();
00162         return GENERIC_EXIT_OK;
00163     }
00164 
00165     QApplication a(argc, argv);
00166     QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHAVTEST);
00167 
00168     int retval;
00169     if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
00170         return retval;
00171 
00172     if (!cmdline.toString("display").isEmpty())
00173     {
00174         MythUIHelper::SetX11Display(cmdline.toString("display"));
00175     }
00176 
00177     if (!cmdline.toString("geometry").isEmpty())
00178     {
00179         MythUIHelper::ParseGeometryOverride(cmdline.toString("geometry"));
00180     }
00181 
00182     QString filename = "";
00183     if (!cmdline.toString("infile").isEmpty())
00184         filename = cmdline.toString("infile");
00185     else if (cmdline.GetArgs().size() >= 1)
00186         filename = cmdline.GetArgs()[0];
00187 
00188     gContext = new MythContext(MYTH_BINARY_VERSION);
00189     if (!gContext->Init())
00190     {
00191         LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
00192         return GENERIC_EXIT_NO_MYTHCONTEXT;
00193     }
00194 
00195     cmdline.ApplySettingsOverride();
00196 
00197     setuid(getuid());
00198 
00199     QString themename = gCoreContext->GetSetting("Theme");
00200     QString themedir = GetMythUI()->FindThemeDir(themename);
00201     if (themedir.isEmpty())
00202     {
00203         QString msg = QString("Fatal Error: Couldn't find theme '%1'.")
00204             .arg(themename);
00205         LOG(VB_GENERAL, LOG_ERR, msg);
00206         return GENERIC_EXIT_NO_THEME;
00207     }
00208 
00209     GetMythUI()->LoadQtConfig();
00210 
00211 #if defined(Q_OS_MACX)
00212     // Mac OS X doesn't define the AudioOutputDevice setting
00213 #else
00214     QString auddevice = gCoreContext->GetSetting("AudioOutputDevice");
00215     if (auddevice.isEmpty())
00216     {
00217         LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Audio not configured, you need "
00218                                  "to run 'mythfrontend', not 'mythtv'.");
00219         return GENERIC_EXIT_SETUP_ERROR;
00220     }
00221 #endif
00222 
00223     MythMainWindow *mainWindow = GetMythMainWindow();
00224     mainWindow->Init();
00225 
00226     if (cmdline.toBool("test"))
00227     {
00228         int seconds = 5;
00229         if (!cmdline.toString("seconds").isEmpty())
00230             seconds = cmdline.toInt("seconds");
00231         VideoPerformanceTest *test = new VideoPerformanceTest(filename, false,
00232                     cmdline.toBool("decodeonly"), seconds,
00233                     cmdline.toBool("deinterlace"));
00234         test->Test();
00235         delete test;
00236     }
00237     else
00238     {
00239         TV::InitKeys();
00240 
00241         if (!UpgradeTVDatabaseSchema(false))
00242         {
00243             LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Incorrect database schema.");
00244             delete gContext;
00245             return GENERIC_EXIT_DB_OUTOFDATE;
00246         }
00247 
00248         if (filename.isEmpty())
00249         {
00250             TV::StartTV(NULL, kStartTVNoFlags);
00251         }
00252         else
00253         {
00254             ProgramInfo pginfo(filename);
00255             TV::StartTV(&pginfo, kStartTVNoFlags);
00256         }
00257     }
00258     DestroyMythMainWindow();
00259 
00260     delete gContext;
00261 
00262     return GENERIC_EXIT_OK;
00263 }
00264 
00265 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends