File: getVideoExample.cpp

package info (click to toggle)
libaria 2.8.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 13,628 kB
  • ctags: 16,574
  • sloc: cpp: 135,490; makefile: 925; python: 597; java: 570; ansic: 182
file content (164 lines) | stat: -rw-r--r-- 5,104 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include "Aria.h"
#include "ArNetworking.h"

/** @example getVideoExample.cpp
 *
 *  This example client requests video images from the server
 *  and saves them repeatedly to a file named "video.jpg", or
 *  to a series of files ("video1.jpg", "video2.jpg", etc.) if
 *  you give the -counter option. Give the image request rate
 *  in images per second with the -rate option (or use -1 to let
 *  the server decide when to send image; may not work with all servers).
 *
 *  Connect to SAVserver, ACTS, or another video server to get
 *  images. 
 *
 *  To make a movie from the images, you can use ffmpeg on Linux.
 *  First run with frame rate and counter options to save multiple images:
 *    ./getVideoExample -host robothost -port 7272 -rate 20 -counter
 *  Then use ffmpeg:
 *    ffmpeg -i video%d.jpeg -r 20 movie.mpeg
 *  See ffmpeg -h for full list of options.
 */


bool useCounter = false;
unsigned long counter = 1;

double rate = 0;
int rateAsTime = 0;

void jpegHandler(ArNetPacket *packet)
{
  unsigned int width;
  unsigned int height;
  static unsigned char jpeg[50000];
  int jpegSize;
  FILE *file;

  width = packet->bufToUByte2();
  height = packet->bufToUByte2();
  jpegSize = packet->getDataLength() - packet->getDataReadLength();
  if(jpegSize > 50000)
  {
    ArLog::log(ArLog::Normal, "Cannot save image, it's too big. (image is %d bytes, my buffer is 50000 bytes)", jpegSize);
    return;
  }
  packet->bufToData((char *)jpeg, jpegSize);
  char filename[128];
  char tmpFilename[128];
  sprintf(tmpFilename, "tmp.jpg");
  if ((file = ArUtil::fopen(tmpFilename, "wb")) != NULL)
  {
    fwrite(jpeg, jpegSize, 1, file);
    fclose(file);
    if(useCounter)
      snprintf(filename, 64, "video%lu.jpg", counter++);
    else
      strcpy(filename, "video.jpg");
#ifdef WIN32
    // On windows, rename() fails if the new file already exists
    unlink(filename);
#endif
    if (rename(tmpFilename, filename) == 0)
      ArLog::log(ArLog::Normal, "Wrote a %dx%d image, %d bytes, named %s.", width, height, jpegSize, filename);
    else
      ArLog::log(ArLog::Normal, "Wrote a %dx%d image, %d bytes, named %s (could not rename to real name).", width, height, jpegSize, tmpFilename);
  }
  else
    ArLog::log(ArLog::Normal, "Could not write temp file %s", tmpFilename);

  if (rate == 0 || rateAsTime == 0)
  {
    ArLog::log(ArLog::Normal, "Only one frame was requested, so exiting");
    Aria::exit(0);
  }
}

int main(int argc, char **argv)
{

#ifndef WIN32
  ArDaemonizer daemonizer(&argc, argv, false);
  bool isDaemonized = false;
  if (!daemonizer.daemonize())
  {
    ArLog::log(ArLog::Terse, "Could not daemonize process");
    exit(1);
  }
  if (daemonizer.isDaemonized())
    isDaemonized = true;
#endif

  Aria::init();
  ArLog::init(ArLog::File, ArLog::Normal, "getVideoLog.txt", true, true, true);
  
  ArArgumentParser argParser(&argc, argv);
  argParser.loadDefaultArguments();

  ArClientSimpleConnector clientConnector(&argParser);

  if(argParser.checkParameterArgumentDouble("-rate", &rate) && rate != 0.0)
  {
    if(rate == -1)
      rateAsTime = -1;
    else
      rateAsTime = ArMath::roundInt(1000.0 / rate);
  }

  useCounter = argParser.checkArgument("-counter");

  if(!Aria::parseArgs() || !argParser.checkHelpAndWarnUnparsed())
  {
    Aria::logOptions();
    ArLog::log(ArLog::Terse, "\n\n%s options:\n-rate <FramesPerSecondAsDouble> (If this isn't given, then the program will take one frame then exit, note that it is a double (so you can do .5 to do one frame per 2 seconds) and that if you set it to be too fast you'll saturate the robot's bandwidth and make it useless)\n-counter (default no)\n", argv[0]);

    ArLog::log(ArLog::Terse, "\n\nNotes:\nThis program saves the images as video.jpg if you aren't using a counter, or video<counter>.jpg if you are using the counter.\nIt puts its logs into getVideoLog.txt, and overwrites it whenever it runs\n");
    
    return 1;
  }
  


  ArClientBase client;
  if (!clientConnector.connectClient(&client))
  {
    ArLog::log(ArLog::Normal, "Could not connect to server, exiting\n");
    exit(1);
  }    

  ArGlobalFunctor1<ArNetPacket *> jpegHandlerCB(&jpegHandler);

  if(client.dataExists("getPictureCam1"))
  {
    ArLog::log(ArLog::Normal, "Requesting images using \"getPictureCam1\" request.");
    client.addHandler("getPictureCam1", &jpegHandlerCB);
    if (rate != 0 && rateAsTime != 0)
      client.request("getPictureCam1", rateAsTime); 
    else
      client.requestOnce("getPictureCam1");
  } 
  else if(client.dataExists("sendVideo"))
  {
    ArLog::log(ArLog::Normal, "Server does not have \"getPictureCam1\" request, requesting images using old \"sendVideo\" request.");
    client.addHandler("sendVideo", &jpegHandlerCB);
    if (rate != 0 && rateAsTime != 0)
      client.request("sendVideo", rateAsTime); 
    else
      client.requestOnce("sendVideo"); 
  }
  else
  {
    ArLog::log(ArLog::Terse, "Error: Server does not have \"getPictureCam1\" or \"sendVideo\" request, cannot request images.");
    Aria::exit(2);
  }


  client.run();

  Aria::shutdown();
  return 0;
}