From bf2937ef7a51692fde384a38c24d3d0eed601fda Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 8 Jun 2011 21:09:03 +0000 Subject: added basic streamer code --- src/Makefile | 1 + src/gstdvbbackend.c | 23 ++++----- src/sig_handler.c | 1 + src/streamer.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/streamer.h | 45 +++++++++++++++++ 5 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 src/streamer.c create mode 100644 src/streamer.h diff --git a/src/Makefile b/src/Makefile index 320b243..df4d8d0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,6 +35,7 @@ C_OBJS := log.o \ slist.o \ string_list.o \ sysexec.o \ + streamer.o \ gstdvbbackend.o C_SRCS := $(C_OBJS:%.o=%.c) diff --git a/src/gstdvbbackend.c b/src/gstdvbbackend.c index 7d3a0c0..0134391 100644 --- a/src/gstdvbbackend.c +++ b/src/gstdvbbackend.c @@ -36,6 +36,7 @@ #include "string_list.h" #include "log.h" #include "daemon.h" +#include "streamer.h" static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) { @@ -82,6 +83,7 @@ int main_loop(options_t* opt) GMainLoop *loop; GstElement *pipeline, *source, *sink; GstBus *bus; + streamer_t streamer; loop = g_main_loop_new(NULL, FALSE); pipeline = gst_pipeline_new("gstdvbbackend"); @@ -106,19 +108,15 @@ int main_loop(options_t* opt) g_object_set(G_OBJECT(source), "trans-mode", 1, NULL); // 8k g_object_set(G_OBJECT(source), "guard", 4, NULL); // AUTO - sink = gst_element_factory_make ("tcpserversink", "streamer-sink"); - if(!sink) { - log_printf(ERROR, "Error creating streamer sink"); - gst_object_unref(GST_OBJECT(source)); + int ret = streamer_init(&streamer, loop, NULL, "9001"); + if(ret) { gst_object_unref(GST_OBJECT(pipeline)); gst_object_unref(GST_OBJECT(loop)); - return -1; + return ret; } - g_object_set(G_OBJECT(sink), "host", "127.0.0.1", NULL); - g_object_set(G_OBJECT(sink), "port", 9001, NULL); - gst_bin_add_many(GST_BIN(pipeline), source, sink, NULL); - gst_element_link_many(source, sink, NULL); + gst_bin_add_many(GST_BIN(pipeline), source, streamer.sink_, NULL); + gst_element_link_many(source, streamer.sink_, NULL); bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); gst_bus_add_watch(bus, bus_call, loop); gst_object_unref(bus); @@ -129,8 +127,11 @@ int main_loop(options_t* opt) gst_element_set_state(pipeline, GST_STATE_PLAYING); signal_start(loop); - g_main_loop_run(loop); - signal_stop(); + ret = streamer_start(&streamer); + if(!ret) { + g_main_loop_run(loop); + signal_stop(); + } log_printf(NOTICE, "Stopping pipeline"); gst_element_set_state (pipeline, GST_STATE_NULL); diff --git a/src/sig_handler.c b/src/sig_handler.c index 68a95cb..c4b94b6 100644 --- a/src/sig_handler.c +++ b/src/sig_handler.c @@ -27,6 +27,7 @@ #include "log.h" +#include #include "sig_handler.h" #include diff --git a/src/streamer.c b/src/streamer.c new file mode 100644 index 0000000..fd1223d --- /dev/null +++ b/src/streamer.c @@ -0,0 +1,137 @@ +/* + * gstdvbbackend + * + * gstdvbbackend is a small programm which captures a given set of dvb + * channels from one dvb device and provides the streams via minimal http. + * + * + * Copyright (C) 2011 Christian Pointner + * + * This file is part of gstdvbbackend. + * + * gstdvbbackend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * gstdvbbackend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gstdvbbackend. If not, see . + */ + +#include + +#include + +#include +#include + +#include "streamer.h" + +#include "datatypes.h" +#include "log.h" + +static void added_cb(GstElement* sink, gint fd, gpointer data) +{ + gint num_fds; + g_object_get(G_OBJECT(sink), "num_fds", &num_fds, NULL); + log_printf(INFO, "fdsink: successfully added client %d (sink has now %d fds)", fd, num_fds); +} + +static void removed_cb(GstElement* sink, gint fd, gpointer data) +{ + gint num_fds; + g_object_get(G_OBJECT(sink), "num_fds", &num_fds, NULL); + log_printf(INFO, "fdsink: successfully removed client %d (sink has now %d fds)", fd, num_fds); +} + +static void fdremoved_cb(GstElement* sink, gint fd, gpointer data) +{ + gint num_fds; + g_object_get(G_OBJECT(sink), "num_fds", &num_fds, NULL); + log_printf(INFO, "fdsink: successfully removed fd %d (sink has now %d fds)", fd, num_fds); +} + +int streamer_init(streamer_t* streamer, GMainLoop *loop, const char* host, const char* port) +{ + if(!streamer) + return -1; + + // TODO: init server socket here + + streamer->loop_ = loop; + streamer->sink_ = gst_element_factory_make("multifdsink", "streamer"); + if(!streamer->sink_) { + log_printf(ERROR, "the streamer object could not be created. Exiting."); + return -1; + } + + // TODO: how the heck should we get the right value? 3 means keyframe... + g_object_set(G_OBJECT(streamer->sink_), "recover-policy", 3, NULL); + g_signal_connect(G_OBJECT(streamer->sink_), "client-added", G_CALLBACK(added_cb), streamer); + g_signal_connect(G_OBJECT(streamer->sink_), "client-removed", G_CALLBACK(removed_cb), streamer); + g_signal_connect(G_OBJECT(streamer->sink_), "client-fd-removed", G_CALLBACK(fdremoved_cb), streamer); + + streamer->thread_ = NULL; + return 0; +} + +static void add_fd(streamer_t* streamer, int fd) +{ + log_printf(INFO, "adding fd %d to fdsink", fd); + g_signal_emit_by_name(G_OBJECT(streamer->sink_), "add", fd, NULL); +} + +static void remove_fd(streamer_t* streamer, int fd) +{ + log_printf(INFO, "removing fd %d from fdsink", fd); + g_signal_emit_by_name(G_OBJECT(streamer->sink_), "remove-flush", fd, NULL); +} + +static gpointer streamer_thread_func(gpointer data) +{ + streamer_t *streamer = (streamer_t*)data; + log_printf(NOTICE, "streamer thread started"); + + GstBuffer* buf = NULL; + for(;;) { + // TODO: call accept here + sleep(100); + break; + } + + log_printf(NOTICE, "streamer thread stopped"); + g_main_loop_quit(streamer->loop_); + return NULL; +} + +int streamer_start(streamer_t* streamer) +{ + if(!streamer) + return -1; + + streamer->thread_ = g_thread_create(streamer_thread_func, streamer, TRUE, NULL); + if(!streamer->thread_) { + log_printf(ERROR, "streamer thread could not be started"); + return -1; + } + + return 0; +} + +void streamer_stop(streamer_t* streamer) +{ + if(!streamer) + return; + + // TODO: close server socket here + + if(streamer->thread_) { + log_printf(NOTICE, "waiting for streamer thread to stop"); + g_thread_join(streamer->thread_); + } +} diff --git a/src/streamer.h b/src/streamer.h new file mode 100644 index 0000000..069787d --- /dev/null +++ b/src/streamer.h @@ -0,0 +1,45 @@ +/* + * gstdvbbackend + * + * gstdvbbackend is a small programm which captures a given set of dvb + * channels from one dvb device and provides the streams via minimal http. + * + * + * Copyright (C) 2011 Christian Pointner + * + * This file is part of gstdvbbackend. + * + * gstdvbbackend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * gstdvbbackend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gstdvbbackend. If not, see . + */ + +#ifndef RHARCHIVE_streamer_h_INCLUDED +#define RHARCHIVE_streamer_h_INCLUDED + +#include +#include + +struct streamer_struct { + GMainLoop *loop_; + GstElement* sink_; + GThread* thread_; + char* host_; + char* port_; +}; +typedef struct streamer_struct streamer_t; + +int streamer_init(streamer_t* streamer, GMainLoop *loop, const char* host, const char* port); +int streamer_start(streamer_t* streamer); +void streamer_stop(streamer_t* streamer); + +#endif -- cgit v1.2.3