-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
169 lines (154 loc) · 6.29 KB
/
main.cpp
File metadata and controls
169 lines (154 loc) · 6.29 KB
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
165
166
167
168
169
#include <QApplication>
#include <gst/gst.h>
// #include "streaming_window.h"
#include "mainwindow.h"
extern "C"
{
#include <gst/interfaces/xoverlay.h>
}
#include <iostream>
#include <unistd.h>
#include <ctime>
#include <yarp/os/Port.h>
#include <yarp/os/BufferedPort.h>
#include <yarp/os/Network.h>
//Launch from shell:
// gst-launch v4l2src device=/dev/video2 ! image/jpeg,height=480,width=640 ! jpegdec ! ffmpegcolorspace ! clockoverlay font-desc=\"Sans 12\" halign=left valign=top time-format=\"%Y/%m/%d %H:%M:%S\" ! \
tee name=\"splitter\" splitter. ! queue ! videorate name=\"screenshot\" ! video/x-raw-yuv, width=640, height=480, framerate=1/1 ! jpegenc \
! udpsink host=127.0.0.1 port=1234 rtpbin.send_rtcp_src_0 splitter. ! queue ! x264enc pass=qual quantizer=20 tune=zerolatency ! matroskamux ! filesink location=video1
//To receive
// gst-launch udpsrc port=1234 ! jpegdec ! xvimagesink sync=false
void initSaveVideo(std::string filename, GstElement ** result, std::string device, int port_number, std::string hostname="127.0.0.1")
{
std::string inPipelineDescription = "v4l2src device=";
inPipelineDescription.append(device);
inPipelineDescription.append(" ! image/jpeg,width=640,height=480,framerate=15/1 ! \
jpegdec ! ffmpegcolorspace ! \
clockoverlay font-desc=\"Sans 12\" halign=left valign=top time-format=\"%Y/%m/%d %H:%M:%S\" ! \
tee name=\"splitter\" splitter. ! \
queue ! \
videorate ! video/x-raw-yuv, width=640, height=480, framerate=1/1 ! jpegenc ! udpsink host=127.0.0.1 port=");
inPipelineDescription.append(std::to_string(port_number));
inPipelineDescription.append(" rtpbin.send_rtcp_src_0 ");
inPipelineDescription.append("splitter. ! queue ! x264enc pass=qual quantizer=20 tune=zerolatency name=\"enc\" ! matroskamux name=\"mux\" ! \
filesink location=");
inPipelineDescription.append(filename);
inPipelineDescription.append(" name=\"save\" ");
std::cout<<inPipelineDescription<<std::endl;
GError * error(0);
*result = gst_parse_launch(inPipelineDescription.c_str(), &error);
if (error)
{
std::string msg = std::string("Parsing pipeline failed. Reason: ") + error->message;
throw std::runtime_error(msg);
}
}
// This method is a wonderful hack in order to avoid losing frames, check this other solutions if you are curious
// https://github.com/groakat/chunkyH264
// https://github.com/pedrocr/camerasink
// https://github.com/pedrocr/camerasink/blob/edbe35e11a935fd0ab2c4eab82372c2d03790501/bin/testsave.c
void save(GstElement* pipeline,std::string filename)
{
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
char buffer [80];
strftime (buffer,80,"%Y-%m-%d-%H-%M-%S",now);
std::string temp;
temp.append(buffer);
temp.append("-");
temp.append(filename);
temp.append(".mp4");
std::cout<<"saving file"<<temp<<std::endl;
GstElement* filesink = gst_bin_get_by_name(GST_BIN(pipeline), "save");
GstElement* filemux = gst_bin_get_by_name(GST_BIN(pipeline), "mux");
GstElement* encoder = gst_bin_get_by_name(GST_BIN(pipeline), "enc");
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
// gst_element_set_state(GST_ELEMENT(encoder), GST_STATE_NULL);
// gst_element_set_state(GST_ELEMENT(filemux), GST_STATE_NULL);
// gst_element_set_state(GST_ELEMENT(filesink), GST_STATE_NULL);
g_object_set (G_OBJECT (filesink), "location", temp.c_str(), NULL);
// gst_element_set_state(GST_ELEMENT(encoder), GST_STATE_PLAYING);
// gst_element_set_state(GST_ELEMENT(filemux), GST_STATE_PLAYING);
// gst_element_set_state(GST_ELEMENT(filesink), GST_STATE_PLAYING);
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
}
int main(int argc, char *argv[])
{
if (argc<3)
{
std::cout<<"usage: webcam_rec video0 1234 \n with video name parameter, such as video0, video1 and so on, and a udp port parameter, such as 1234"<<std::endl;
exit(EXIT_FAILURE);
}
// yarp network declaration and check
yarp::os::Network yarp;
if(!yarp.checkNetwork()){
std::cerr <<"yarpserver not running - run yarpserver"<< std::endl;
exit(EXIT_FAILURE);
}
// yarp network initialization
yarp.init();
gst_init(&argc, &argv);
GstElement * pipeline;
std::string prefix=argv[1];//"video0";
int port_number = atoi(argv[2]);//1234
yarp::os::BufferedPort<yarp::os::Bottle> port;
port.open("/camera_rec/"+prefix);
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
char buffer [80];
strftime (buffer,80,"%Y-%m-%d-%H-%M-%S",now);
std::string temp;
temp.append(buffer);
temp.append("-");
temp.append(prefix);
temp.append(".mp4");
initSaveVideo(temp, &pipeline, "/dev/"+prefix,port_number);
int counter=0;
bool exit=false;
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
while(!exit)
{
yarp::os::Bottle* bot_command = port.read(false);
std::string cmd;
if(bot_command != NULL) {
cmd= bot_command->get(0).asString();
}
if (cmd=="quit") exit=true;
if (cmd=="saving")
{
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
}
if (cmd=="not saving")
{
save(pipeline,prefix);
counter=0;
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
}
if (false && cmd.find("period")!=std::string::npos)
{
GstElement* screenshot = gst_bin_get_by_name(GST_BIN(pipeline), "screenshot");
std::string frames=std::to_string(bot_command->get(1).asInt());
frames.append("/1");
std::cout<<"setting framerate of screenshots to "<<frames<<std::endl;
g_object_set (G_OBJECT (screenshot), "framerate", frames.c_str(), NULL);
}
if (cmd=="save")
{
if (counter>5)
{
save(pipeline,prefix);
counter=0;
}
}
counter++;
if (counter==120)
{
save(pipeline,prefix);
counter=0;
}
sleep(1);
}
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
yarp.fini();
return 0;
}