00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef PSYCHO_MPLAYERWRAPPER_C_DEFINED
00039 #define PSYCHO_MPLAYERWRAPPER_C_DEFINED
00040
00041 #include "Psycho/MPlayerWrapper.H"
00042 #include "Component/ComponentOpts.H"
00043 #include "Component/ModelManager.H"
00044 #include "Util/Pause.H"
00045 #include "Util/csignals.H"
00046 #include "Util/Types.H"
00047 #include "GUI/GUIOpts.H"
00048 #include "Util/StringConversions.H"
00049 #include "Util/StringUtil.H"
00050 #include "rutz/pipe.h"
00051 #include "nub/ref.h"
00052 #include "Component/ModelOptionDef.H"
00053 #include <stdlib.h>
00054 #include "Psycho/PsychoDisplay.H"
00055 #include <iostream>
00056 #include <sstream>
00057 #include <string>
00058 #include <stdio.h>
00059 #include <vector>
00060 #include <unistd.h>
00061
00062 const ModelOptionCateg MOC_MPLAYER = {
00063 MOC_SORTPRI_2, "MPlayer-Related Options" };
00064
00065 const ModelOptionDef OPT_MPlayerPath =
00066 { MODOPT_ARG_STRING, "MPlayerPath", &MOC_MPLAYER, OPTEXP_CORE,
00067 "Path for the mplayer application.",
00068 "mplayer-path", '\0', "<std::string>", "/usr/bin/mplayer" };
00069
00070 const ModelOptionDef OPT_MPlayerSound =
00071 { MODOPT_FLAG, "MPlayerSound", &MOC_MPLAYER, OPTEXP_CORE,
00072 "Play sound.", "sound", '\0', "", "true" };
00073
00074 const ModelOptionDef OPT_MPlayerAudioDriver =
00075 { MODOPT_ARG_STRING, "MPlayerAudioDriver", &MOC_MPLAYER, OPTEXP_CORE,
00076 "Audio driver to send to mplayer. If sound does not work try alsa/oss. Other valid options are esd/pulse/jack/nas/sdl/mpegpes/v4l2/pcm. Setting to null is equivalent to --nosound.", "ao", '\0', "<std::string>", "alsa" };
00077
00078 const ModelOptionDef OPT_MPlayerCacheSize =
00079 { MODOPT_ARG(uint), "MPlayerCacheSize", &MOC_MPLAYER, OPTEXP_CORE,
00080 "Amount of memory for precaching the video, in kB.",
00081 "cachesize", '\0', "<uint>", "16384"};
00082
00083 const ModelOptionDef OPT_MPlayerCachePercent =
00084 { MODOPT_ARG(double), "MPlayerCachePercent", &MOC_MPLAYER, OPTEXP_CORE,
00085 "Playback begins when the cache is filled to this percent of the total.",
00086 "cachepercent", '\0', "<0-99>", "50" };
00087
00088
00089 MPlayerWrapper::MPlayerWrapper(OptionManager &mgr,
00090 const std::string& descrName,
00091 const std::string& tagName) :
00092 ModelComponent(mgr, descrName, tagName),
00093 itsEventLog(),
00094 itsPlayingVideo(false),
00095 itsIsFullScreen(&OPT_SDLdisplayFullscreen, this),
00096 itsMPlayerPath(&OPT_MPlayerPath, this),
00097 itsIsSound(&OPT_MPlayerSound, this),
00098 itsAudioDriver(&OPT_MPlayerAudioDriver, this),
00099 itsCacheSize(&OPT_MPlayerCacheSize, this),
00100 itsCachePercent(&OPT_MPlayerCachePercent, this)
00101 {
00102 }
00103
00104
00105 MPlayerWrapper::~MPlayerWrapper()
00106 {}
00107
00108
00109 void MPlayerWrapper::setSourceVideo(std::string fname)
00110 {
00111 itsFileName = fname;
00112 }
00113
00114
00115 void MPlayerWrapper::pushEvent(const std::string& msg, const bool& useLinfo)
00116 {
00117 if (useLinfo)
00118 LINFO("%s", msg.c_str());
00119 if (itsEventLog.isValid())
00120 itsEventLog->pushEvent(msg);
00121 }
00122
00123
00124
00125
00126 int MPlayerWrapper::run(const int argc, const char** argv,
00127 const char* extraArgsDescription,
00128 const int minExtraArgs, const int maxExtraArgs)
00129 {
00130 try
00131 {
00132 return this->tryRun(argc, argv, extraArgsDescription,
00133 minExtraArgs, maxExtraArgs);
00134 }
00135 catch (...)
00136 {
00137 REPORT_CURRENT_EXCEPTION;
00138 }
00139
00140 return 1;
00141 }
00142
00143
00144
00145
00146
00147 int MPlayerWrapper::tryRun(const int argc, const char** argv,
00148 const char* extraArgsDescription,
00149 const int minExtraArgs, const int maxExtraArgs)
00150 {
00151 volatile int signum = 0;
00152 catchsignals(&signum);
00153
00154 try
00155 {
00156
00157 pushEvent(std::string("===== Playing movie: ") +
00158 itsFileName + " =====");
00159
00160 std::string mp_out;
00161 rutz::exec_pipe mphandle("r", itsMPlayerPath.getVal().c_str(), "-fs", itsFileName.c_str(), (const char*) 0);
00162
00163 bool movie_begun = false;
00164 while(std::getline(mphandle.stream(), mp_out, '\r'))
00165 {
00166
00167
00168
00169 movie_begun |= (mp_out.find("A:")!=std::string::npos);
00170
00171
00172 if(movie_begun)
00173 parseStatusLine(mp_out);
00174 }
00175 }
00176 catch (...)
00177 {
00178 fprintf(stderr,"Mplayer initializer failed.\n");
00179 }
00180
00181
00182 return 0;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192 int MPlayerWrapper::runfromSDL(nub::soft_ref<PsychoDisplay> D)
00193 {
00194 try
00195 {
00196
00197
00198
00199 nub::ref<rutz::exec_pipe> mphandle = createMPlayerPipe();
00200 std::string mp_out;
00201
00202 ModelComponent * displayManager(D->getParent());
00203
00204 bool status_displayed = false, movie_begun = false, display_closed=false;
00205
00206
00207
00208 const std::string firstline = "VO: [";
00209 while(std::getline(mphandle->stream(), mp_out, '\r'))
00210
00211 {
00212 status_displayed = (mp_out.find("A:")!=std::string::npos);
00213 movie_begun |= (mp_out.find(firstline)!=std::string::npos);
00214
00215
00216 if(!display_closed && movie_begun)
00217 {
00218
00219 pushEvent("===== Movie starting =====");
00220
00221
00222
00223
00224 while(displayManager->hasSubComponent(D) && displayManager != NULL)
00225 {
00226 LINFO("removing subcomponent from %s", D->getParent()->tagName().c_str());
00227 displayManager->removeSubComponent(*D);
00228 displayManager = D->getParent();
00229 }
00230 pushEvent("===== Closing PsychoDisplay: " +
00231 D->descriptiveName() + " =====");
00232 D->stop();
00233 display_closed = true;
00234 }
00235
00236
00237
00238 if(status_displayed && movie_begun)
00239 {
00240
00241 parseStatusLine(mp_out);
00242 itsPlayingVideo = true;
00243 }
00244 }
00245
00246
00247 itsPlayingVideo = false;
00248 D->start();
00249 D->clearScreen();
00250 }
00251 catch (...)
00252 {
00253 LFATAL("MPlayer initializer failed.");
00254 }
00255
00256 return 0;
00257 }
00258
00259 nub::ref<rutz::exec_pipe> MPlayerWrapper::createMPlayerPipe()
00260 {
00261 const uint maxargs = 20;
00262 char** arglist = new(char* [maxargs]);
00263 for (uint i = 0; i < maxargs; i++)
00264 arglist[i] = new char(50);
00265
00266 int numargs = 0;
00267
00268
00269 arglist[numargs++] = (char*) (itsMPlayerPath.getVal()).c_str();
00270 arglist[numargs++] = (char*) itsFileName.c_str();
00271
00272
00273 if(itsIsFullScreen.getVal())
00274 {
00275 arglist[numargs++] = (char*) "-fs";
00276 arglist[numargs++] = (char*) "-xineramascreen";
00277 arglist[numargs++] = (char*) "0";
00278 }
00279
00280 if(itsIsSound.getVal())
00281 {
00282 arglist[numargs++] = (char*) "-ao";
00283 arglist[numargs++] = (char*) (itsAudioDriver.getVal()).c_str();
00284 }
00285 else
00286 {
00287 arglist[numargs++] = (char*) "-nosound";
00288 }
00289
00290
00291
00292
00293
00294 if(0)
00295 {
00296 arglist[numargs++] = (char*) "-autosync";
00297 arglist[numargs++] = (char*) "30";
00298 }
00299 if(0)
00300 {
00301
00302 arglist[numargs++] = (char*) "-framedrop";
00303 }
00304
00305
00306 if(itsCacheSize.getVal() > 0)
00307 {
00308
00309 arglist[numargs++] = (char*) "-cache";
00310 std::string cacheStr = toStr<int>(itsCacheSize.getVal());
00311 arglist[numargs++] = (char*) cacheStr.c_str();
00312
00313
00314 arglist[numargs++] = (char*) "-cache-min";
00315 std::string percentStr = toStr<double>(itsCachePercent.getVal());
00316 arglist[numargs++] = (char*) percentStr.c_str();
00317
00318 }
00319
00320 arglist[numargs] = (char*) 0;
00321 for(int i = 0; arglist[i]!=NULL; i++)
00322 LINFO("arg %d: \"%s\"", i, arglist[i]);
00323 return nub::ref<rutz::exec_pipe>(new rutz::exec_pipe("r", arglist));
00324 }
00325
00326 void MPlayerWrapper::parseStatusLine(const std::string stat_line)
00327 {
00328
00329
00330 unsigned int num_frames = 1, num_dropped = 0;
00331 static unsigned int num_prev_dropped = 0;
00332 double t_video = 0;
00333
00334 if(sscanf(stat_line.c_str(),"A: %*f V: %lf A-V: %*f ct: %*f %u/%*u %*s %*s %*s %u %*u",
00335 &t_video, &num_frames, &num_dropped)==EOF)
00336 pushEvent("Status line error");
00337 else
00338 {
00339
00340 if(num_frames == 1) num_prev_dropped = 0;
00341
00342
00343 if(num_dropped > num_prev_dropped)
00344 {
00345 pushEvent("MPlayerWrapper - " + toStr<int>(num_dropped - num_prev_dropped) + " frames dropped");
00346 num_prev_dropped = num_dropped;
00347 }
00348
00349
00350 if(!(num_frames==1 && itsPlayingVideo))
00351 pushEvent("MPlayerWrapper - frame " + toStr<int>(num_frames + num_dropped-1)
00352 + " at time " + toStr<double>(t_video));
00353 }
00354
00355 }
00356
00357 #endif
00358