From 991b670bd1e838443cffb94675a7d1456cd6ffe7 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 8 Jun 2011 20:33:51 +0000 Subject: removed writer and filelist (legacy crap) --- src/Makefile | 2 - src/file_list.c | 215 ---------------------------------------------- src/file_list.h | 62 -------------- src/gstdvbbackend.c | 49 ++++++----- src/writer.c | 241 ---------------------------------------------------- src/writer.h | 59 ------------- 6 files changed, 27 insertions(+), 601 deletions(-) delete mode 100644 src/file_list.c delete mode 100644 src/file_list.h delete mode 100644 src/writer.c delete mode 100644 src/writer.h diff --git a/src/Makefile b/src/Makefile index 386251a..320b243 100644 --- a/src/Makefile +++ b/src/Makefile @@ -34,8 +34,6 @@ C_OBJS := log.o \ options.o \ slist.o \ string_list.o \ - writer.o \ - file_list.o \ sysexec.o \ gstdvbbackend.o diff --git a/src/file_list.c b/src/file_list.c deleted file mode 100644 index 60f5181..0000000 --- a/src/file_list.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include - -#include "datatypes.h" -#include "file_list.h" -#include "slist.h" -#include "log.h" - -static void delete_file(void* element) -{ - file_t* deletee = (file_t*)element; - log_printf(INFO, "removing/closing file '%s' -> %d", deletee->path_, deletee->fd_); - if(deletee->path_) free(deletee->path_); - if(deletee->fd_ >= 0) close(deletee->fd_); - if(deletee->pp_child_) free_child(deletee->pp_child_); -} - -int file_list_init(file_list_t* list) -{ - list->mutex_ = g_mutex_new(); - if(!list->mutex_) - return -2; - - return slist_init(&(list->list_), &delete_file); -} - -void file_list_clear(file_list_t* list) -{ - g_mutex_lock(list->mutex_); - slist_clear(&(list->list_)); - g_mutex_unlock(list->mutex_); -} - -file_t* file_list_add(file_list_t* list, struct tm* time, const char* type, const char* format, const char* dir, mode_t mode) -{ - if(!list || !(list->mutex_)) - return NULL; - - file_t* tmp = malloc(sizeof(file_t)); - if(!tmp) - return NULL; - - log_printf(INFO, "%s time: %02d:%02d:%02d on %d.%d.%d%s", type, time->tm_hour, time->tm_min, time->tm_sec, time->tm_mday, time->tm_mon+1, time->tm_year+1900, time->tm_isdst > 0 ? " (DST)": ""); - - char name[256]; - strftime(name, sizeof(name), format, time); - asprintf(&(tmp->path_), "%s/%s", dir, name); - if(!tmp->path_) { - free(tmp); - return NULL; - } - - log_printf(INFO, "%s filename is: %s(.?)", type, tmp->path_); - tmp->fd_ = FILE_CLOSED; - tmp->mode_ = mode; - tmp->pp_child_ = NULL; - - g_mutex_lock(list->mutex_); - if(slist_add(&(list->list_), tmp) == NULL) { - g_mutex_unlock(list->mutex_); - free(tmp->path_); - free(tmp); - return NULL; - } - g_mutex_unlock(list->mutex_); - - return tmp; -} - -int file_list_remove(file_list_t* list, int fd) -{ - if(!list || !(list->mutex_)) - return -1; - - g_mutex_lock(list->mutex_); - slist_element_t* tmp = list->list_.first_; - while(tmp) { - if(((file_t*)tmp->data_)->fd_ == fd) { - slist_remove(&(list->list_), tmp->data_); - break; - } - tmp = tmp->next_; - } - g_mutex_unlock(list->mutex_); - - return 0; -} - -int file_list_call_post_process(file_list_t* list, int fd, const char* script) -{ - if(!list || !(list->mutex_)) - return -1; - - g_mutex_lock(list->mutex_); - slist_element_t* tmp = list->list_.first_; - while(tmp) { - if(((file_t*)tmp->data_)->fd_ == fd) { - log_printf(INFO, "calling post processing for '%s'", ((file_t*)tmp->data_)->path_); - close(((file_t*)tmp->data_)->fd_); - ((file_t*)tmp->data_)->fd_ = FILE_POST_PROCESS; - - char* const argv[] = { script, ((file_t*)tmp->data_)->path_, NULL }; - char* const evp[] = { NULL }; - ((file_t*)tmp->data_)->pp_child_ = rh_exec(script, argv, evp); - if(!((file_t*)tmp->data_)->pp_child_) - slist_remove(&(list->list_), tmp->data_); - - break; - } - tmp = tmp->next_; - } - g_mutex_unlock(list->mutex_); - - return 0; -} - -int file_list_waitpid(file_list_t* list) -{ - if(!list || !(list->mutex_)) - return -1; - - g_mutex_lock(list->mutex_); - slist_element_t* tmp = list->list_.first_; - while(tmp) { - if(((file_t*)tmp->data_)->fd_ == FILE_POST_PROCESS) { - int ret = rh_waitpid(((file_t*)tmp->data_)->pp_child_, NULL); - file_t* deletee = tmp->data_; - tmp = tmp->next_; - if(ret) - slist_remove(&(list->list_), deletee); - } - else - tmp = tmp->next_; - } - g_mutex_unlock(list->mutex_); - - return 0; -} - -int open_file(file_t* file) -{ - if(!file || file->fd_ != FILE_CLOSED) // file already open! - return -1; - - char* orig_path = file->path_; - int cnt = 0; - do { - file->fd_ = open(file->path_, O_WRONLY | O_CREAT | O_EXCL, file->mode_); - if(file->fd_ < 0) { - if(errno != EEXIST) { - // TODO: thread safe strerror - log_printf(ERROR, "can't open file '%s': %s", file->path_, strerror(errno)); - if(orig_path != file->path_) - free(orig_path); - file->fd_ = FILE_CLOSED; - return -1; - } - cnt++; - char* tmp; - asprintf(&tmp, "%s.%d", orig_path, cnt); - if(!tmp) { - if(orig_path != file->path_) - free(orig_path); - return -2; - } - - if(file->path_ != orig_path) - free(file->path_); - file->path_ = tmp; - } - fchmod(file->fd_, file->mode_); - } - while(file->fd_ < 0); - - if(orig_path != file->path_) - free(orig_path); - - log_printf(INFO, "opened file '%s' -> %d", file->path_, file->fd_); - - return 0; -} diff --git a/src/file_list.h b/src/file_list.h deleted file mode 100644 index a2cf8a0..0000000 --- a/src/file_list.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 GSTDVBBACKEND_file_list_h_INCLUDED -#define GSTDVBBACKEND_file_list_h_INCLUDED - -#include -#include - -#include - -#include "slist.h" -#include "sysexec.h" - -#define FILE_CLOSED -1 -#define FILE_POST_PROCESS -2 - -struct file_struct { - int fd_; - char* path_; - mode_t mode_; - child_t* pp_child_; -}; -typedef struct file_struct file_t; - -struct file_list_struct { - slist_t list_; - GMutex* mutex_; -}; -typedef struct file_list_struct file_list_t; - -int file_list_init(file_list_t* list); -void file_list_clear(file_list_t* list); -file_t* file_list_add(file_list_t* list, struct tm* time, const char* type, const char* format, const char* dir, mode_t mode); -int file_list_remove(file_list_t* list, int fd); -int file_list_call_post_process(file_list_t* list, int fd, const char* script); -int file_list_waitpid(file_list_t* list); -int open_file(file_t* file); - -#endif diff --git a/src/gstdvbbackend.c b/src/gstdvbbackend.c index 5777ed0..0cb9dd4 100644 --- a/src/gstdvbbackend.c +++ b/src/gstdvbbackend.c @@ -36,7 +36,6 @@ #include "string_list.h" #include "log.h" #include "daemon.h" -#include "writer.h" static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) { @@ -81,9 +80,8 @@ int main_loop(options_t* opt) log_printf(INFO, "entering main loop"); GMainLoop *loop; - GstElement *pipeline, *source; + GstElement *pipeline, *source, *sink; GstBus *bus; - writer_t writer; loop = g_main_loop_new(NULL, FALSE); pipeline = gst_pipeline_new("gstdvbbackend"); @@ -92,26 +90,37 @@ int main_loop(options_t* opt) return -1; } - int ret = writer_init(&writer, loop, opt->name_format_, opt->mode_, opt->output_dir_, opt->interval_, opt->offset_, opt->post_process_); - if(ret) { + source = gst_element_factory_make ("dvbsrc", "dvb-source"); + if(!source) { + log_printf(ERROR, "Error creating dvb source"); gst_object_unref(GST_OBJECT(pipeline)); gst_object_unref(GST_OBJECT(loop)); - return ret; + return -1; } - - GError *error = NULL; - source = gst_parse_bin_from_description(opt->src_bin_desc_, TRUE, &error); - if(!source || error) { - log_printf(ERROR, "Source Bin Description Parser Error: %s", error ? error->message : "unknown"); - g_error_free(error); - gst_object_unref(GST_OBJECT(writer.sink_)); + g_object_set(G_OBJECT(source), "adapter", 0, NULL); + g_object_set(G_OBJECT(source), "frontend", 0, NULL); + g_object_set(G_OBJECT(source), "frequency", 514000000, NULL); + g_object_set(G_OBJECT(source), "polarity", "H", NULL); + g_object_set(G_OBJECT(source), "pids", "5010:5011", NULL); + g_object_set(G_OBJECT(source), "bandwidth", 0, NULL); // 8Mbit/s + g_object_set(G_OBJECT(source), "modulation", 1, NULL); // QAM 16 + g_object_set(G_OBJECT(source), "trans-mode", 1, NULL); // 8k + g_object_set(G_OBJECT(source), "code-rate-lp", 9, NULL); // AUTO + 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)); gst_object_unref(GST_OBJECT(pipeline)); gst_object_unref(GST_OBJECT(loop)); return -1; } + 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, writer.sink_, NULL); - gst_element_link_many(source, writer.sink_, NULL); + gst_bin_add_many(GST_BIN(pipeline), source, sink, NULL); + gst_element_link_many(source, sink, NULL); bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); gst_bus_add_watch(bus, bus_call, loop); gst_object_unref(bus); @@ -122,18 +131,14 @@ int main_loop(options_t* opt) gst_element_set_state(pipeline, GST_STATE_PLAYING); signal_start(loop); - ret = writer_start(&writer); - if(!ret) { - g_main_loop_run(loop); - signal_stop(); - } + g_main_loop_run(loop); + signal_stop(); log_printf(NOTICE, "Stopping pipeline"); gst_element_set_state (pipeline, GST_STATE_NULL); - writer_stop(&writer); gst_object_unref(GST_OBJECT(pipeline)); - return ret; + return 0; } int main(int argc, char* argv[]) diff --git a/src/writer.c b/src/writer.c deleted file mode 100644 index 43e60b4..0000000 --- a/src/writer.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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 - -#include "writer.h" - -#include "datatypes.h" -#include "log.h" -#include "file_list.h" - -static int init_time_boundaries(writer_t* writer) -{ - if(!writer) - return; - - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); - - struct tm bd_time; - localtime_r(&(now.tv_sec), &bd_time); - - writer->current_ = file_list_add(&(writer->files_), &bd_time, "current", writer->name_format_, writer->output_dir_, writer->mode_); - if(writer->current_ == NULL) return -2; - - bd_time.tm_sec = 0; - bd_time.tm_min = 0; - time_t T = mktime(&bd_time); - T+=3600; - localtime_r(&T, &bd_time); - - struct timespec b = { T, 0 }; - writer->next_boundary_ = b; - - writer->next_ = file_list_add(&(writer->files_), &bd_time, "next", writer->name_format_, writer->output_dir_, writer->mode_); - if(writer->next_ == NULL) return -2; - - return 0; -} - -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); - - writer_t *writer = (writer_t*)data; - if(writer->post_process_) - file_list_call_post_process(&(writer->files_), fd, writer->post_process_); - else - file_list_remove(&(writer->files_), fd); -} - -int writer_init(writer_t* writer, GMainLoop *loop, const char* name_format, mode_t mode, const char* output_dir, int interval, int offset, const char* post_process) -{ - if(!writer) - return -1; - - writer->loop_ = loop; - writer->sink_ = gst_element_factory_make("multifdsink", "writer"); - if(!writer->sink_) { - log_printf(ERROR, "the writer 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(writer->sink_), "recover-policy", 3, NULL); - g_signal_connect(G_OBJECT(writer->sink_), "client-added", G_CALLBACK(added_cb), writer); - g_signal_connect(G_OBJECT(writer->sink_), "client-removed", G_CALLBACK(removed_cb), writer); - g_signal_connect(G_OBJECT(writer->sink_), "client-fd-removed", G_CALLBACK(fdremoved_cb), writer); - - writer->clock_ = gst_system_clock_obtain(); - if(!writer->clock_) { - log_printf(ERROR, "unable to obtain the system clock"); - return -1; - } - writer->name_format_ = name_format; - writer->mode_ = mode; - writer->output_dir_ = output_dir; - writer->interval_ = interval * GST_MSECOND; - writer->offset_ = offset * GST_MSECOND; - writer->post_process_ = post_process; - writer->clock_id_ = NULL; - writer->thread_ = NULL; - int ret = file_list_init(&(writer->files_)); - if(ret) return ret; - - return init_time_boundaries(writer); -} - -static void add_fd(writer_t* writer, int fd) -{ - log_printf(INFO, "adding fd %d to fdsink", fd); - g_signal_emit_by_name(G_OBJECT(writer->sink_), "add", fd, NULL); -} - -static void remove_fd(writer_t* writer, int fd) -{ - log_printf(INFO, "removing fd %d from fdsink", fd); - g_signal_emit_by_name(G_OBJECT(writer->sink_), "remove-flush", fd, NULL); -} - -static int check_boundaries(writer_t* writer) -{ - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); - - GstClockTime tmp = GST_TIMESPEC_TO_TIME(now); - GstClockTime boundary = GST_TIMESPEC_TO_TIME(writer->next_boundary_); - tmp -= writer->offset_; - if(tmp >= boundary) { - struct tm now_bd; - localtime_r(&(now.tv_sec), &now_bd); - log_printf(INFO, "boundary reached! it's now: %02d:%02d:%02d.%06d on %d.%d.%d%s (%d ms offset)", now_bd.tm_hour, now_bd.tm_min, now_bd.tm_sec, now.tv_nsec/1000, now_bd.tm_mday, now_bd.tm_mon+1, now_bd.tm_year+1900, now_bd.tm_isdst > 0 ? " (DST)": "", GST_TIME_AS_MSECONDS(writer->offset_)); - - int ret = open_file(writer->next_); - if(ret) return ret; // TODO: stop writer on open_file error ??? - - add_fd(writer, writer->next_->fd_); - remove_fd(writer, writer->current_->fd_); - - int old_fd = writer->current_->fd_; - writer->current_ = writer->next_; - - writer->next_boundary_.tv_sec += 3600; - struct tm bd_time; - localtime_r(&(writer->next_boundary_.tv_sec), &bd_time); - - writer->next_ = file_list_add(&(writer->files_), &bd_time, "next", writer->name_format_, writer->output_dir_, writer->mode_); - if(writer->next_ == NULL) return -2; - } - - return 0; -} - -static gpointer writer_thread_func(gpointer data) -{ - writer_t *writer = (writer_t*)data; - log_printf(NOTICE, "writer thread started"); - - GstBuffer* buf = NULL; - for(;;) { - GstClockReturn wret = gst_clock_id_wait(writer->clock_id_, NULL); - if(GST_CLOCK_UNSCHEDULED == wret) - break; - if(GST_CLOCK_EARLY == wret) - continue; - - int ret = check_boundaries(writer); - if(ret) break; - - ret = file_list_waitpid(&(writer->files_)); - if(ret) break; - } - - log_printf(NOTICE, "writer thread stopped"); - g_main_loop_quit(writer->loop_); - return NULL; -} - -int writer_start(writer_t* writer) -{ - if(!writer) - return -1; - - int ret = open_file(writer->current_); - if(ret) - return ret; - - add_fd(writer, writer->current_->fd_); - - writer->clock_id_ = gst_clock_new_periodic_id(writer->clock_, 0, writer->interval_); - if(!writer->clock_id_) { - log_printf(ERROR, "clock id could not be created"); - return -1; - } - writer->thread_ = g_thread_create(writer_thread_func, writer, TRUE, NULL); - if(!writer->thread_) { - log_printf(ERROR, "writer thread could not be started"); - return -1; - } - - return 0; -} - -void writer_stop(writer_t* writer) -{ - if(!writer) - return; - - file_list_clear(&(writer->files_)); - if(writer->clock_id_) { - gst_clock_id_unschedule(writer->clock_id_); - } - if(writer->thread_) { - log_printf(NOTICE, "waiting for writer thread to stop"); - g_thread_join(writer->thread_); - } - gst_object_unref(GST_OBJECT(writer->clock_)); -} diff --git a/src/writer.h b/src/writer.h deleted file mode 100644 index cab40bd..0000000 --- a/src/writer.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 GSTDVBBACKEND_writer_h_INCLUDED -#define GSTDVBBACKEND_writer_h_INCLUDED - -#include -#include -#include -#include - -#include "file_list.h" - -struct writer_struct { - GMainLoop *loop_; - GstElement* sink_; - GstClock* clock_; - GstClockID clock_id_; - GThread* thread_; - const char* name_format_; - const char* output_dir_; - mode_t mode_; - GstClockTime interval_; - GstClockTime offset_; - const char* post_process_; - file_list_t files_; - file_t* current_; - file_t* next_; - struct timespec next_boundary_; -}; -typedef struct writer_struct writer_t; - -int writer_init(writer_t* writer, GMainLoop *loop, const char* name_format, mode_t mode, const char* output_dir, int interval, int offset, const char* post_process); -int writer_start(writer_t* writer); -void writer_stop(writer_t* writer); - -#endif -- cgit v1.2.3