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 #include <mxcpcFramewiseMxPEGDecoder.h>
00028 #include <mxcpcStreamFile.h>
00029 #include <mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.h>
00030 #include <mxcpcFramewiseMxPEGScanDecoderSoftwareOnly.h>
00031 #include <mxcpcDefaultMxPEGDecoderBackEnd.h>
00032 #include <mxcpcMxPEGRawFrameDumper.h>
00033 #include <mxcpcMJPEGWriter.h>
00034 #include <mxcpcDevNullStatusMessageHandler.h>
00035 #include <mxcpcTime.h>
00036
00037 #include <cstdio>
00038 #include <unistd.h>
00039
00040
00041
00042 void print_usage(const char *progname) {
00043
00044 std::printf("%s : convert an MxPEG stream to MJPEG\n", progname);
00045 std::printf("%s\n", mxcpc::getVersionString());
00046 std::printf("\n");
00047 std::printf("Usage: %s [options]\n", progname);
00048 std::printf("\n");
00049 std::printf("Options:\n");
00050 std::printf("-h, --help : this message\n");
00051 std::printf("-f <mxpeg_stream_file> : reads input from <mxpeg_stream_file> "
00052 "rather than from stdin\n");
00053 std::printf("-o <output_file> : writes the generated MJPEG stream "
00054 "to <output_file> rather than to "
00055 "stdout\n");
00056 std::printf("-s <separator_string> : HTTP mode, inserts a MIME separator "
00057 "between JPEG frames (useful in CGI "
00058 "scripts)\n");
00059 std::printf("-raw : raw mode, does not output MJPEG "
00060 "stream, but raw RGB data instead "
00061 "(3 bytes per pixel)\n");
00062 std::printf("-yuv : to be used with above raw mode, "
00063 "outputs frames in yv12 YUV format "
00064 "instead of RGB\n");
00065 std::printf("-sofps <framerate> : to be used with above raw mode, "
00066 "stabilizes output framerate at the "
00067 "specified value\n");
00068 std::printf("\n");
00069 std::printf("Examples:\n");
00070 std::printf("cat file1.mxg file2.mxg | %s > file.mjpg\n", progname);
00071 std::printf("curl 'http://<camera_ip>/control/faststream.jpg?stream=MxPEG' "
00072 "| %s -s MOBOTIX_Fast_Serverpush -o file.mjpg\n", progname);
00073 std::printf("C:\\> type file1.mxg | %s > file.mjpg\n", progname);
00074 std::printf("\n");
00075 }
00076
00077
00078 void process_command_args(int argc, char **argv,
00079 bool *show_usage,
00080 const char **mime_separator,
00081 const char **stream_filename,
00082 const char **out_filename,
00083 bool *raw,
00084 bool *yuv,
00085 float *sofs) {
00086
00087 int arg_i;
00088
00089 *show_usage = false;
00090 *mime_separator = 0;
00091 *stream_filename = 0;
00092 *out_filename = 0;
00093 *raw = false;
00094 *yuv = false;
00095 *sofs = -1.0f;
00096
00097 arg_i = 1;
00098 while(arg_i < argc) {
00099
00100 if( !std::strcmp(argv[arg_i], "-h")
00101 || !std::strcmp(argv[arg_i], "--help")) {
00102 *show_usage = true;
00103 arg_i++;
00104 }
00105 else if(!std::strcmp(argv[arg_i], "-s")) {
00106 if(arg_i + 1 < argc) {
00107 *mime_separator = argv[arg_i + 1];
00108 arg_i += 2;
00109 }
00110 else {
00111 *show_usage = true;
00112 }
00113 }
00114 else if(!std::strcmp(argv[arg_i], "-f")) {
00115 if(arg_i + 1 < argc) {
00116 *stream_filename = argv[arg_i + 1];
00117 arg_i += 2;
00118 }
00119 else {
00120 *show_usage = true;
00121 }
00122 }
00123 else if(!std::strcmp(argv[arg_i], "-o")) {
00124 if(arg_i + 1 < argc) {
00125 *out_filename = argv[arg_i + 1];
00126 arg_i += 2;
00127 }
00128 else {
00129 *show_usage = true;
00130 }
00131 }
00132 else if(!std::strcmp(argv[arg_i], "-raw")) {
00133 *raw = true;
00134 arg_i ++;
00135 }
00136 else if(!std::strcmp(argv[arg_i], "-yuv")) {
00137 *yuv = true;
00138 arg_i ++;
00139 }
00140 else if(!std::strcmp(argv[arg_i], "-sofps")) {
00141 if(arg_i + 1 < argc) {
00142 *sofs = std::atof(argv[arg_i + 1]);
00143 if(*sofs < .01f) *sofs = .01f;
00144 if(*sofs > 1000.0f) *sofs = 1000.0f;
00145 arg_i += 2;
00146 }
00147 else {
00148 *show_usage = true;
00149 }
00150 }
00151 else {
00152 *show_usage = true;
00153 }
00154
00155 if(*show_usage) break;
00156 }
00157 }
00158
00159
00160
00161 int main(int argc, char **argv) {
00162
00163 bool show_usage;
00164 const char *mime_separator;
00165 const char *stream_filename;
00166 const char *out_filename;
00167 const char *progname;
00168 bool raw;
00169 bool yuv;
00170 float sofs;
00171 mxcpcFramewiseMxPEGDecoder *decoder;
00172 mxcpcStreamFile *stream_file;
00173 mxcpcMJPEGWriter *writer;
00174 mxcpcMxPEGRawFrameDumper *frame_dumper;
00175 mxcpcBinaryFileWriter *raw_writer;
00176 mxcpcTime da_time;
00177 int cycle_time, time_left, timeout;
00178
00179 progname = "mxg2mjpg";
00180
00181
00182 process_command_args(argc, argv,
00183 &show_usage,
00184 &mime_separator,
00185 &stream_filename,
00186 &out_filename,
00187 &raw,
00188 &yuv,
00189 &sofs);
00190 if(show_usage) {
00191 print_usage(progname);
00192 std::exit(0);
00193 }
00194
00195
00196
00197
00198 mxcpc::setStatusMessageHandler(new mxcpcDevNullStatusMessageHandler());
00199
00200
00201 if(stream_filename)
00202 stream_file = new mxcpcStreamFile(stream_filename);
00203 else
00204 stream_file = new mxcpcStreamFile(STDIN_FILENO);
00205
00206
00207 writer = 0;
00208 raw_writer = 0;
00209 if(!raw) {
00210 if(out_filename)
00211 writer = new mxcpcMJPEGWriter(out_filename, mime_separator);
00212 else
00213 writer = new mxcpcMJPEGWriter(STDOUT_FILENO, mime_separator);
00214 }
00215 else {
00216 if(out_filename)
00217 raw_writer = new mxcpcBinaryFileWriter(out_filename);
00218 else
00219 raw_writer = new mxcpcBinaryFileWriter(STDOUT_FILENO);
00220 }
00221
00222
00223 if(!raw) {
00224 decoder = new mxcpcFramewiseMxPEGDecoder(
00225 stream_file,
00226 new mxcpcDefaultMxPEGDecoderBackEnd(),
00227 new mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly(
00228 writer
00229 )
00230 );
00231 }
00232 else {
00233 frame_dumper = new mxcpcMxPEGRawFrameDumper(raw_writer, yuv);
00234 decoder = new mxcpcFramewiseMxPEGDecoder(
00235 stream_file,
00236 frame_dumper,
00237 new mxcpcFramewiseMxPEGScanDecoderSoftwareOnly()
00238 );
00239 }
00240
00241
00242 if(raw & sofs > 0.0f) {
00243
00244 cycle_time = (int)(1000.0f / sofs);
00245 time_left = 0;
00246
00247 frame_dumper->setExplicitDumpModeEnabled(true);
00248
00249 while(decoder->sourceStillUp()) {
00250
00251
00252 time_left -= da_time.elapsed();
00253
00254
00255 while(time_left <= 0) {
00256 frame_dumper->dumpFrame();
00257 time_left += cycle_time;
00258 }
00259
00260
00261
00262 timeout = time_left;
00263 if(timeout < 10) timeout = 10;
00264 if(timeout > 1000) timeout = 1000;
00265 stream_file->setTimedBlockModeEnabled(true, timeout);
00266
00267
00268 decoder->decode(2048);
00269 }
00270
00271 }
00272 else {
00273 while(decoder->sourceStillUp())
00274 decoder->decode(2048);
00275 }
00276
00277
00278 delete decoder;
00279 mxcpc::setStatusMessageHandler(0);
00280 std::exit(0);
00281 }
00282