summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2014-09-04 02:20:34 +0200
committerChristian Pointner <equinox@spreadspace.org>2014-09-04 02:20:34 +0200
commit72aad834774598a50cbaf4bedc22e8101b02cef5 (patch)
tree081d07f3e41a757e2aaa15bb388196a9181b5ead /src
parentremoved useless sysexec (diff)
added send stream pipeline with options
Diffstat (limited to 'src')
-rw-r--r--src/options.c102
-rw-r--r--src/options.h16
-rw-r--r--src/sydra.c61
3 files changed, 154 insertions, 25 deletions
diff --git a/src/options.c b/src/options.c
index afe9a37..260438b 100644
--- a/src/options.c
+++ b/src/options.c
@@ -199,12 +199,25 @@ int options_parse(options_t* opt, int argc, char* argv[])
PARSE_STRING_LIST("-L","--log", opt->log_targets_)
PARSE_BOOL_PARAM("-U", "--debug", opt->debug_)
PARSE_STRING_PARAM("-n","--appname", opt->appname_)
- PARSE_STRING_PARAM("-R","--rec-dir", opt->rec_dir_)
+ PARSE_STRING_PARAM("-vs","--video-source", opt->video_src_)
+ PARSE_STRING_PARAM("-ve","--video-encoder", opt->video_enc_)
+ PARSE_STRING_PARAM("-vp","--video-payloader", opt->video_payloader_)
+ PARSE_STRING_PARAM("-V","--videosink", opt->videosink_)
+ PARSE_STRING_PARAM("-as","--audio-source", opt->audio_src_)
+ PARSE_STRING_PARAM("-ae","--audio-encoder-stream", opt->audio_enc_stream_)
+ PARSE_STRING_PARAM("-ap","--audio-payloader", opt->audio_payloader_)
+ PARSE_STRING_PARAM("-o","--rtp-host", opt->rtp_host_)
+ PARSE_INT_PARAM("-O","--rtp-port-base", opt->rtp_port_base_, 10)
+ PARSE_STRING_PARAM("-ar","--audio-encoder-rec", opt->audio_enc_rec_)
+ PARSE_STRING_PARAM("-m","--rec-mux", opt->rec_mux_)
PARSE_STRING_PARAM("-r","--rec-name-format", opt->rec_name_format_)
else
return i;
}
+ if(opt->rtp_port_base_ < 1 || opt->rtp_port_base_ > 65535)
+ return -4;
+
if(opt->debug_) {
string_list_add(&opt->log_targets_, "stdout:5");
opt->daemonize_ = 0;
@@ -239,8 +252,23 @@ void options_default(options_t* opt)
string_list_init(&opt->log_targets_);
opt->debug_ = 0;
opt->appname_ = NULL;
- opt->rec_dir_ = strdup("./recordings/");
- opt->rec_name_format_ = strdup("%Y-%m-%d_%H-%M-$S");
+
+ opt->video_src_ = strdup("v4l2src ! videoconvert ! videoscale ! video/x-raw,format=I420,width=864,height=480,framerate=25/1,pixel-aspect-ratio=1/1");
+ opt->video_enc_ = strdup("vp8enc keyframe-max-dist=25 error-resilient=2 end-usage=1 target-bitrate=1800000 cpu-used=4 deadline=1000000 threads=2");
+ opt->video_payloader_ = strdup("rtpvp8pay");
+ opt->videosink_ = strdup("xvimagesink");
+
+ opt->audio_src_ = strdup("autoaudiosrc ! audio/x-raw,format=S16LE,channels=1,rate=48000");
+ opt->audio_enc_stream_ = strdup("opusenc bitrate=64000 cbr=true packet-loss-percentage=0 inband-fec=false");
+ opt->audio_payloader_ = strdup("rtpopuspay");
+
+ opt->rtp_host_ = strdup("127.0.0.1");
+ opt->rtp_port_base_ = 5100;
+
+ opt->audio_enc_rec_ = strdup("audioconvert ! vorbisenc bitrate=96000");
+ opt->rec_mux_ = strdup("matroskamux");
+
+ opt->rec_name_format_ = strdup("./recordings/%Y-%m-%d_%H-%M-%S.mkv");
}
void options_clear(options_t* opt)
@@ -261,8 +289,26 @@ void options_clear(options_t* opt)
string_list_clear(&opt->log_targets_);
if(opt->appname_)
free(opt->appname_);
- if(opt->rec_dir_)
- free(opt->rec_dir_);
+ if(opt->video_src_)
+ free(opt->video_src_);
+ if(opt->video_enc_)
+ free(opt->video_enc_);
+ if(opt->video_payloader_)
+ free(opt->video_payloader_);
+ if(opt->videosink_)
+ free(opt->videosink_);
+ if(opt->audio_src_)
+ free(opt->audio_src_);
+ if(opt->audio_enc_stream_)
+ free(opt->audio_enc_stream_);
+ if(opt->audio_payloader_)
+ free(opt->audio_payloader_);
+ if(opt->rtp_host_)
+ free(opt->rtp_host_);
+ if(opt->audio_enc_rec_)
+ free(opt->audio_enc_rec_);
+ if(opt->rec_mux_)
+ free(opt->rec_mux_);
if(opt->rec_name_format_)
free(opt->rec_name_format_);
}
@@ -281,7 +327,17 @@ void options_print_usage()
printf(" add a log target, can be invoked several times\n");
printf(" [-U|--debug] don't daemonize and log to stdout with maximum log level\n");
printf(" [-n|--appname] <name> set the application name (will be used by xvimagesink for window title\n");
- printf(" [-R|--rec-dir] <path> path to the recording directory\n");
+ printf(" [-vs|--video-source pipeline for raw video (i.e. videotestsrc)\n");
+ printf(" [-ve|--video-encoder pipeline for video encoder (stream and recording)\n");
+ printf(" [-vp|--video-payloader video payloader element (i.e. rtpvp8pay\n");
+ printf(" [-V|--videosink video sink element (i.e. xvimagesink\n");
+ printf(" [-as|--audio-source pipeline for raw audio (audiotestsrc)\n");
+ printf(" [-ae|--audio-encoder-stream pipeline for audio encoder (stream only)\n");
+ printf(" [-ap|--audio-payloader audio payloader element (i.e. rptopuspay)\n");
+ printf(" [-o|--rtp-host remote host for RTP packets\n");
+ printf(" [-O|--rtp-port-base base number for remote ports\n");
+ printf(" [-ar|--audio-encoder-rec pipeline for audio encoder (recording only)\n");
+ printf(" [-m|--rec-mux muxer elemenent (i.e. matroskamux)\n");
printf(" [-r|--rec-name-format] <format> the recording file name format, see manpage of strftime for the syntax\n");
}
@@ -296,16 +352,26 @@ void options_print(options_t* opt)
if(!opt)
return;
- printf("progname: '%s'\n", opt->progname_);
- printf("daemonize: %d\n", opt->daemonize_);
- printf("username: '%s'\n", opt->username_);
- printf("groupname: '%s'\n", opt->groupname_);
- printf("chroot_dir: '%s'\n", opt->chroot_dir_);
- printf("pid_file: '%s'\n", opt->pid_file_);
- printf("log_targets: \n");
- string_list_print(&opt->log_targets_, " '", "'\n");
- printf("debug: %s\n", !opt->debug_ ? "false" : "true");
- printf("appname: >>%s<<\n", opt->appname_);
- printf("rec_output_dir: '%s'\n", opt->rec_dir_);
- printf("rec_name_format: '%s'\n", opt->rec_name_format_);
+ printf(" progname: '%s'\n", opt->progname_);
+ printf(" daemonize: %d\n", opt->daemonize_);
+ printf(" username: '%s'\n", opt->username_);
+ printf(" groupname: '%s'\n", opt->groupname_);
+ printf(" chroot_dir: '%s'\n", opt->chroot_dir_);
+ printf(" pid_file: '%s'\n", opt->pid_file_);
+ printf(" log_targets: \n");
+ string_list_print(&opt->log_targets_, " '", "'\n");
+ printf(" debug: %s\n", !opt->debug_ ? "false" : "true");
+ printf(" appname: >>%s<<\n", opt->appname_);
+ printf(" video_src: >>%s<<\n", opt->video_src_);
+ printf(" video_enc: >>%s<<\n", opt->video_enc_);
+ printf(" video_payloader: >>%s<<\n", opt->video_payloader_);
+ printf(" video_sink: >>%s<<\n", opt->videosink_);
+ printf(" audio_src: >>%s<<\n", opt->audio_src_);
+ printf(" audio_enc_stream: >>%s<<\n", opt->audio_enc_stream_);
+ printf(" audio_payloader: >>%s<<\n", opt->audio_payloader_);
+ printf(" rtp_host: >>%s<<\n", opt->rtp_host_);
+ printf(" rtp_port_base: %d\n", opt->rtp_port_base_);
+ printf(" audio_enc_rec: >>%s<<\n", opt->audio_enc_rec_);
+ printf(" rec_mux: >>%s<<\n", opt->rec_mux_);
+ printf(" rec_name_format: '%s'\n", opt->rec_name_format_);
}
diff --git a/src/options.h b/src/options.h
index a89bb25..31197b5 100644
--- a/src/options.h
+++ b/src/options.h
@@ -45,7 +45,21 @@ struct options_struct {
int debug_;
char* appname_;
- char* rec_dir_;
+
+ char* video_src_;
+ char* video_enc_;
+ char* video_payloader_;
+ char* videosink_;
+
+ char* audio_src_;
+ char* audio_enc_stream_;
+ char* audio_payloader_;
+
+ char* rtp_host_;
+ int rtp_port_base_;
+
+ char* audio_enc_rec_;
+ char* rec_mux_;
char* rec_name_format_;
};
typedef struct options_struct options_t;
diff --git a/src/sydra.c b/src/sydra.c
index ec87af8..b4b8d9b 100644
--- a/src/sydra.c
+++ b/src/sydra.c
@@ -27,11 +27,13 @@
* along with sydra. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
+#include <time.h>
#include <gst/gst.h>
@@ -75,17 +77,19 @@ static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
break;
}
default:
+ log_printf(WARNING, "unkonwn message %d", GST_MESSAGE_TYPE(msg));
break;
}
return TRUE;
}
+
int main_loop(options_t* opt)
{
log_printf(INFO, "entering main loop");
GMainLoop *loop;
- GstElement *pipeline, *source;
+ GstElement *pipeline, *sender;
GstBus *bus;
loop = g_main_loop_new(NULL, FALSE);
@@ -95,17 +99,62 @@ int main_loop(options_t* opt)
return -1;
}
+ struct timespec now;
+ clock_gettime(CLOCK_REALTIME, &now);
+ struct tm bd_time;
+ localtime_r(&(now.tv_sec), &bd_time);
+ char recfile[1024]; //TODO: fix this hardcoded length
+ strftime(recfile, sizeof(recfile), opt->rec_name_format_, &bd_time);
+
+ int rtp_port_v = opt->rtp_port_base_;
+ int rtcp_port_v = opt->rtp_port_base_ + 100;
+ int rtp_port_a = opt->rtp_port_base_ + 200;
+ int rtcp_port_a = opt->rtp_port_base_ + 300;
+
+ char* sender_str;
+ int slen = asprintf(&sender_str, "rtpbin name=rtpbin \
+ %s ! tee name=vt \
+ vt. ! queue silent=true ! %s ! tee name=cvt \
+ cvt. ! %s ! rtpbin.send_rtp_sink_0 \
+ rtpbin.send_rtp_src_0 ! udpsink port=%d host=%s \
+ rtpbin.send_rtcp_src_0 ! udpsink port=%d host=%s sync=false async=false \
+ %s ! tee name=at \
+ at. ! queue silent=true ! %s ! %s ! rtpbin.send_rtp_sink_1 \
+ rtpbin.send_rtp_src_1 ! udpsink port=%d host=%s \
+ rtpbin.send_rtcp_src_1 ! udpsink port=%d host=%s sync=false async=false \
+ %s name=recmux ! filesink location=\"%s\" \
+ cvt. ! queue silent=true ! recmux. \
+ at. ! queue silent=true ! %s ! recmux. \
+ vt. ! queue silent=true ! textoverlay text=\" local \" shaded-background=true halignment=center valignment=baseline font-desc=\"Sans 18\" ! %s",
+ opt->video_src_, opt->video_enc_, opt->video_payloader_, rtp_port_v, opt->rtp_host_, rtcp_port_v, opt->rtp_host_,
+ opt->audio_src_, opt->audio_enc_stream_, opt->audio_payloader_, rtp_port_a, opt->rtp_host_, rtcp_port_a, opt->rtp_host_,
+ opt->rec_mux_, recfile, opt->audio_enc_rec_, opt->videosink_);
+
+ if(slen < 0) {
+ log_printf(ERROR, "memory error while constructing sender pipeline");
+ gst_object_unref(GST_OBJECT(pipeline));
+ gst_object_unref(GST_OBJECT(loop));
+ return -1;
+ }
+
+ printf("\n\n\n");
+ printf("%s", sender_str);
+ printf("\n\n\n");
+
+
GError *error = NULL;
- source = gst_parse_bin_from_description("videotestsrc ! xvimagesink", TRUE, &error);
- if(!source || error) {
- log_printf(ERROR, "Source Bin Description Parser Error: %s", error ? error->message : "unknown");
+ sender = gst_parse_bin_from_description(sender_str, TRUE, &error);
+ if(!sender || error) {
+ log_printf(ERROR, "Sending Bin Description Parser Error: %s", error ? error->message : "unknown");
g_error_free(error);
+ free(sender_str);
gst_object_unref(GST_OBJECT(pipeline));
gst_object_unref(GST_OBJECT(loop));
return -1;
}
+ free(sender_str);
- gst_bin_add_many(GST_BIN(pipeline), source, NULL);
+ gst_bin_add_many(GST_BIN(pipeline), sender, NULL);
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);
@@ -140,7 +189,7 @@ int main(int argc, char* argv[])
if(ret == -3)
options_print_version();
if(ret == -4)
- fprintf(stderr, "the interval must be bigger than 0\n");
+ fprintf(stderr, "the port number is invalid\n");
if(ret != -2 && ret != -3 && ret != -4)
options_print_usage();