Revision f35c1c76 src/main/milhouse.cpp
| b/src/main/milhouse.cpp | ||
|---|---|---|
| 3 | 3 |
* http://www.sat.qc.ca |
| 4 | 4 |
* All rights reserved. |
| 5 | 5 |
* |
| 6 |
* This file is part of [propulse]ART.
|
|
| 6 |
* This file is part of Scenic.
|
|
| 7 | 7 |
* |
| 8 |
* [propulse]ART is free software: you can redistribute it and/or modify
|
|
| 8 |
* Scenic is free software: you can redistribute it and/or modify
|
|
| 9 | 9 |
* it under the terms of the GNU General Public License as published by |
| 10 | 10 |
* the Free Software Foundation, either version 3 of the License, or |
| 11 | 11 |
* (at your option) any later version. |
| 12 | 12 |
* |
| 13 |
* [propulse]ART is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 13 |
* Scenic is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 14 | 14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | 15 |
* GNU General Public License for more details. |
| 16 | 16 |
* |
| 17 | 17 |
* You should have received a copy of the GNU General Public License |
| 18 |
* along with [propulse]ART. If not, see <http://www.gnu.org/licenses/>.
|
|
| 18 |
* along with Scenic. If not, see <http://www.gnu.org/licenses/>.
|
|
| 19 | 19 |
* |
| 20 | 20 |
*/ |
| 21 | 21 |
|
| 22 |
#include <cstdlib> |
|
| 23 | 22 |
#include <iostream> |
| 24 | 23 |
|
| 25 |
#include "util.h" |
|
| 24 |
#include "milhouse.h" |
|
| 25 |
#include "util/log_writer.h" |
|
| 26 | 26 |
|
| 27 |
#include "gtk_utils.h"
|
|
| 27 |
#include "gutil/gutil.h"
|
|
| 28 | 28 |
|
| 29 |
#include "gst/videoFactory.h" |
|
| 30 |
#include "gst/audioFactory.h" |
|
| 31 |
#include "gst/messageDispatcher.h" |
|
| 29 |
#include "gst/video_factory.h" |
|
| 30 |
#include "gst/audio_factory.h" |
|
| 32 | 31 |
#include "gst/pipeline.h" |
| 33 |
#include "gst/rtpReceiver.h" |
|
| 34 |
#include "gst/videoConfig.h" |
|
| 35 |
#include "playback.h" |
|
| 32 |
#include "gst/rtp_receiver.h" |
|
| 33 |
#include "gst/video_config.h" |
|
| 36 | 34 |
|
| 37 |
#include "milhouse.h" |
|
| 38 |
#include "milhouseLogger.h" |
|
| 39 |
#include "programOptions.h" |
|
| 35 |
#include "milhouse_logger.h" |
|
| 36 |
#include "program_options.h" |
|
| 37 |
#include "rtsp/rtsp_server.h" |
|
| 38 |
#include "rtsp/rtsp_client.h" |
|
| 40 | 39 |
|
| 41 | 40 |
namespace po = boost::program_options; |
| 41 |
void Milhouse::runAsRTSPClient(const po::variables_map &options) |
|
| 42 |
{
|
|
| 43 |
LOG_DEBUG("Running as RTSP client");
|
|
| 44 |
Pipeline pipeline; // Pipeline will go out of scope last |
|
| 45 |
RTSPClient client(options, &pipeline); |
|
| 46 |
client.run(options["timeout"].as<int>()); |
|
| 47 |
} |
|
| 48 |
|
|
| 49 |
void Milhouse::runAsRTSPServer(const po::variables_map &options) |
|
| 50 |
{
|
|
| 51 |
LOG_DEBUG("Running as RTSP server");
|
|
| 52 |
// TODO: create a server that uses rtsp-cam-media-factory, see rtsp/examples/gst-rtsp-cam.c |
|
| 53 |
RTSPServer server(options); |
|
| 54 |
server.run(options["timeout"].as<int>()); |
|
| 55 |
} |
|
| 42 | 56 |
|
| 43 | 57 |
void Milhouse::runAsReceiver(const po::variables_map &options, bool enableVideo, bool enableAudio) |
| 44 | 58 |
{
|
| 45 | 59 |
using std::tr1::shared_ptr; |
| 60 |
using std::string; |
|
| 46 | 61 |
|
| 47 | 62 |
LOG_DEBUG("Running as receiver");
|
| 48 | 63 |
Pipeline pipeline; // Pipeline will go out of scope last |
| 49 |
if (options["debug"].as<std::string>() == "gst-debug")
|
|
| 64 |
if (options["debug"].as<string>() == "gst-debug") |
|
| 50 | 65 |
pipeline.makeVerbose(); |
| 51 | 66 |
|
| 52 |
Playback playback(pipeline); |
|
| 53 |
shared_ptr<VideoReceiver> vRx; |
|
| 54 | 67 |
shared_ptr<AudioReceiver> aRx; |
| 68 |
shared_ptr<VideoReceiver> vRx; |
|
| 55 | 69 |
|
| 56 |
if (enableVideo) |
|
| 57 |
{
|
|
| 58 |
vRx = videofactory::buildVideoReceiver(pipeline, options); |
|
| 59 |
} |
|
| 60 | 70 |
if (enableAudio) |
| 61 |
{
|
|
| 62 | 71 |
aRx = audiofactory::buildAudioReceiver(pipeline, options); |
| 63 | 72 |
|
| 64 |
if (options["disable-jack-autoconnect"].as<bool>()) |
|
| 65 |
MessageDispatcher::sendMessage("disable-jack-autoconnect");
|
|
| 66 |
} |
|
| 67 |
|
|
| 68 |
playback.start(); |
|
| 69 |
|
|
| 70 |
/// These options are more like commands, they are dispatched after playback starts |
|
| 71 |
if (options.count("jitterbuffer"))
|
|
| 72 |
RtpReceiver::setLatency(options["jitterbuffer"].as<int>()); |
|
| 73 |
|
|
| 74 | 73 |
if (enableVideo) |
| 75 |
{
|
|
| 76 |
if(options["fullscreen"].as<bool>()) |
|
| 77 |
MessageDispatcher::sendMessage("fullscreen");
|
|
| 78 |
MessageDispatcher::sendMessage("window-title", options["window-title"].as<std::string>());
|
|
| 79 |
} |
|
| 74 |
vRx = videofactory::buildVideoReceiver(pipeline, options); |
|
| 75 |
|
|
| 76 |
pipeline.start(); |
|
| 80 | 77 |
|
| 81 | 78 |
LOG_DEBUG("Running main loop");
|
| 82 | 79 |
gutil::runMainLoop(options["timeout"].as<int>()); |
| 83 | 80 |
LOG_DEBUG("main loop has finished");
|
| 84 |
|
|
| 85 |
playback.stop(); |
|
| 86 | 81 |
} |
| 87 | 82 |
|
| 88 | 83 |
|
| ... | ... | |
| 95 | 90 |
if (options["debug"].as<std::string>() == "gst-debug") |
| 96 | 91 |
pipeline.makeVerbose(); |
| 97 | 92 |
|
| 98 |
Playback playback(pipeline); |
|
| 99 |
shared_ptr<VideoSender> vTx; |
|
| 100 | 93 |
shared_ptr<AudioSender> aTx; |
| 101 |
|
|
| 102 |
if (enableVideo) |
|
| 103 |
{
|
|
| 104 |
vTx = videofactory::buildVideoSender(pipeline, options); |
|
| 105 |
} |
|
| 94 |
shared_ptr<VideoSender> vTx; |
|
| 106 | 95 |
|
| 107 | 96 |
if (enableAudio) |
| 108 |
{
|
|
| 109 | 97 |
aTx = audiofactory::buildAudioSender(pipeline, options); |
| 110 | 98 |
|
| 111 |
if (options["disable-jack-autoconnect"].as<bool>()) |
|
| 112 |
MessageDispatcher::sendMessage("disable-jack-autoconnect");
|
|
| 113 |
} |
|
| 99 |
if (enableVideo) |
|
| 100 |
vTx = videofactory::buildVideoSender(pipeline, options); |
|
| 114 | 101 |
|
| 115 |
playback.start();
|
|
| 102 |
pipeline.start();
|
|
| 116 | 103 |
|
| 117 | 104 |
gutil::runMainLoop(options["timeout"].as<int>()); |
| 118 |
|
|
| 119 |
playback.stop(); |
|
| 120 | 105 |
} |
| 121 | 106 |
|
| 122 | 107 |
|
| ... | ... | |
| 129 | 114 |
if (options["debug"].as<std::string>() == "gst-debug") |
| 130 | 115 |
pipeline.makeVerbose(); |
| 131 | 116 |
|
| 132 |
Playback playback(pipeline); |
|
| 133 | 117 |
shared_ptr<LocalVideo> localVideo; |
| 134 | 118 |
if (enableVideo) |
| 135 | 119 |
{
|
| ... | ... | |
| 142 | 126 |
{
|
| 143 | 127 |
LOG_DEBUG("LOCAL AUDIO");
|
| 144 | 128 |
localAudio = audiofactory::buildLocalAudio(pipeline, options); |
| 145 |
if (options["disable-jack-autoconnect"].as<bool>()) |
|
| 146 |
MessageDispatcher::sendMessage("disable-jack-autoconnect");
|
|
| 147 | 129 |
} |
| 148 | 130 |
|
| 149 |
playback.start(); |
|
| 150 |
|
|
| 151 |
if (enableVideo) |
|
| 152 |
{
|
|
| 153 |
if(options["fullscreen"].as<bool>()) |
|
| 154 |
MessageDispatcher::sendMessage("fullscreen");
|
|
| 155 |
MessageDispatcher::sendMessage("window-title", options["window-title"].as<std::string>());
|
|
| 156 |
} |
|
| 131 |
pipeline.start(); |
|
| 157 | 132 |
|
| 158 | 133 |
gutil::runMainLoop(options["timeout"].as<int>()); |
| 159 |
|
|
| 160 |
playback.stop(); |
|
| 161 | 134 |
} |
| 162 | 135 |
|
| 163 | 136 |
|
| ... | ... | |
| 170 | 143 |
|
| 171 | 144 |
short Milhouse::run(int argc, char **argv) |
| 172 | 145 |
{
|
| 146 |
using std::string; |
|
| 173 | 147 |
po::options_description desc(ProgramOptions::createDefaultOptions()); |
| 174 | 148 |
po::variables_map options; |
| 175 | 149 |
po::store(po::parse_command_line(argc, argv, desc), options); |
| 176 | 150 |
po::notify(options); |
| 177 | 151 |
|
| 178 |
if (options.count("help") or argc == 1)
|
|
| 152 |
if (options.count("help") or argc == 1)
|
|
| 179 | 153 |
return usage(desc); |
| 180 | 154 |
|
| 181 |
MilhouseLogger logger(options["debug"].as<std::string>()); // just instantiate, his base class will know what to do
|
|
| 155 |
MilhouseLogger logger(options["debug"].as<string>()); // just instantiate, his base class will know what to do
|
|
| 182 | 156 |
|
| 183 | 157 |
LOG_DEBUG("Built on " << __DATE__ << " at " << __TIME__);
|
| 184 | 158 |
|
| 185 | 159 |
if (options["version"].as<bool>()) |
| 186 | 160 |
{
|
| 187 |
#ifdef SVNVERSION |
|
| 188 |
LOG_PRINT("milhouse version " << PACKAGE_VERSION << " Svn Revision: " << SVNVERSION << std::endl);
|
|
| 189 |
#else |
|
| 190 | 161 |
LOG_PRINT("milhouse version " << PACKAGE_VERSION << std::endl);
|
| 191 |
#endif |
|
| 192 | 162 |
return 0; |
| 193 | 163 |
} |
| 194 | 164 |
|
| 195 |
// maybe just have a separate function that checks for all these standalone
|
|
| 165 |
// maybe just have a separate function that checks for all these standalone |
|
| 196 | 166 |
// calls and quits instead of all here |
| 197 | 167 |
if (options["list-v4l2"].as<bool>()) |
| 198 | 168 |
return VideoSourceConfig::listV4lDevices(); |
| ... | ... | |
| 200 | 170 |
return VideoSourceConfig::listCameras(); |
| 201 | 171 |
else if (options.count("v4l2-standard"))
|
| 202 | 172 |
{
|
| 203 |
VideoSourceConfig::setStandard(options["videodevice"].as<std::string>(), options["v4l2-standard"].as<std::string>());
|
|
| 173 |
VideoSourceConfig::setStandard(options["videodevice"].as<string>(), options["v4l2-standard"].as<string>());
|
|
| 204 | 174 |
return 0; |
| 205 | 175 |
} |
| 206 | 176 |
else if (options.count("v4l2-input"))
|
| 207 | 177 |
{
|
| 208 |
VideoSourceConfig::setInput(options["videodevice"].as<std::string>(), options["v4l2-input"].as<int>());
|
|
| 178 |
VideoSourceConfig::setInput(options["videodevice"].as<string>(), options["v4l2-input"].as<int>()); |
|
| 209 | 179 |
return 0; |
| 210 | 180 |
} |
| 211 | 181 |
|
| 212 |
if (options["dump-pipeline"].as<bool>()) |
|
| 213 |
setenv("GST_DEBUG_DUMP_DOT_DIR", ".", 0 /* don't override current value if present*/);
|
|
| 214 |
|
|
| 215 | 182 |
// wrapper so main doesn't need to know about gst and gtk |
| 216 | 183 |
gutil::init_gst_gtk(argc, argv); |
| 184 |
|
|
| 217 | 185 |
if (options["gst-version"].as<bool>()) |
| 218 | 186 |
{
|
| 219 | 187 |
// this was handled internally by gst_init's argv parsing |
| ... | ... | |
| 221 | 189 |
} |
| 222 | 190 |
|
| 223 | 191 |
if (options["max-channels"].as<bool>()) |
| 224 |
{
|
|
| 225 |
audiofactory::printMaxChannels(options["audiocodec"].as<std::string>()); |
|
| 192 |
{
|
|
| 193 |
audiofactory::printMaxChannels(options["audiocodec"].as<string>()); |
|
| 194 |
return 0; |
|
| 195 |
} |
|
| 196 |
|
|
| 197 |
/*----------------------------------------------*/ |
|
| 198 |
// RTSP mode |
|
| 199 |
/*----------------------------------------------*/ |
|
| 200 |
|
|
| 201 |
if (options["rtsp-server"].as<bool>()) |
|
| 202 |
{
|
|
| 203 |
runAsRTSPServer(options); |
|
| 226 | 204 |
return 0; |
| 227 | 205 |
} |
| 228 |
|
|
| 206 |
else if (options["rtsp-client"].as<bool>()) |
|
| 207 |
{
|
|
| 208 |
runAsRTSPClient(options); |
|
| 209 |
return 0; |
|
| 210 |
} |
|
| 211 |
|
|
| 212 |
/*----------------------------------------------*/ |
|
| 213 |
// Local preview mode |
|
| 214 |
/*----------------------------------------------*/ |
|
| 215 |
|
|
| 229 | 216 |
bool enableLocalVideo = options["localvideo"].as<bool>(); |
| 230 | 217 |
bool enableLocalAudio = options["localaudio"].as<bool>(); |
| 231 | 218 |
if (enableLocalVideo or enableLocalAudio) |
| 232 | 219 |
{
|
| 220 |
LOG_DEBUG("Running as local preview");
|
|
| 233 | 221 |
runAsLocal(options, enableLocalVideo, enableLocalAudio); |
| 234 | 222 |
return 0; |
| 235 | 223 |
} |
| 236 | 224 |
|
| 237 |
if ((not options["sender"].as<bool>() and not options["receiver"].as<bool>()) |
|
| 225 |
/*----------------------------------------------*/ |
|
| 226 |
// Send/receive mode |
|
| 227 |
/*----------------------------------------------*/ |
|
| 228 |
|
|
| 229 |
if ((not options["sender"].as<bool>() and not options["receiver"].as<bool>()) |
|
| 238 | 230 |
or (options["sender"].as<bool>() and options["receiver"].as<bool>())) |
| 239 | 231 |
{
|
| 240 |
LOG_ERROR("argument error: must be sender OR receiver OR localvideo.");
|
|
| 232 |
LOG_ERROR("Must be run as "
|
|
| 233 |
"-s, -r, --localvideo, --localaudio, --rtsp-server OR --rtsp-client." |
|
| 234 |
" See --help."); |
|
| 241 | 235 |
return 1; |
| 242 | 236 |
} |
| 243 | 237 |
|
| 244 |
bool enableVideo = options.count("videoport");
|
|
| 245 |
bool enableAudio = options.count("audioport");
|
|
| 246 | 238 |
|
| 239 |
bool enableVideo = not options["disable-video"].as<bool>(); |
|
| 240 |
bool enableAudio = not options["disable-audio"].as<bool>(); |
|
| 247 | 241 |
|
| 248 | 242 |
if (not enableVideo and not enableAudio) |
| 249 | 243 |
{
|
| 250 |
LOG_ERROR("argument error: must provide videoport and/or audioport. see --help");
|
|
| 244 |
LOG_ERROR("argument error: cannot disable video and audio. see --help");
|
|
| 251 | 245 |
return 1; |
| 252 | 246 |
} |
| 253 | 247 |
|
| ... | ... | |
| 255 | 249 |
if (enableAudio and enableVideo) |
| 256 | 250 |
if (options["videoport"].as<int>() == options["audioport"].as<int>()) |
| 257 | 251 |
{
|
| 258 |
LOG_ERROR("argument error: videoport and audioport cannot be equal");
|
|
| 252 |
LOG_ERROR("argument error: videoport and audioport cannot be equal");
|
|
| 259 | 253 |
return 1; |
| 260 | 254 |
} |
| 261 | 255 |
|
| 262 |
if (options["receiver"].as<bool>())
|
|
| 256 |
if (options["receiver"].as<bool>()) |
|
| 263 | 257 |
runAsReceiver(options, enableVideo, enableAudio); |
| 264 |
else
|
|
| 258 |
else |
|
| 265 | 259 |
runAsSender(options, enableVideo, enableAudio); |
| 266 | 260 |
|
| 267 | 261 |
return 0; |
Also available in: Unified diff