/** * gstreamill_job_start: * @job: (in): json type of job description. * * Returns: json type of job execution result. */ gchar * gstreamill_job_start (Gstreamill *gstreamill, gchar *job_desc) { gchar *p, *name; Job *job; if (!jobdesc_is_valid (job_desc)) { p = g_strdup_printf ("{\n \"result\": \"failure\",\n \"reason\": \"invalid job\"\n}"); return p; } if (jobdesc_is_live (job_desc)) { GST_ERROR ("live job arrived:\n%s", job_desc); } else { GST_ERROR ("transcode job arrived:\n%s", job_desc); } /* create job object */ name = jobdesc_get_name (job_desc); if (get_job (gstreamill, name) != NULL) { GST_ERROR ("start job failure, duplicated name %s.", name); p = g_strdup_printf ("{\n \"result\": \"failure\",\n \"reason\": \"duplicated name\"\n}"); g_free (name); return p; } job = job_new ("job", job_desc, "name", name, "exe_path", gstreamill->exe_path, NULL); g_free (name); /* job initialize */ job->log_dir = gstreamill->log_dir; g_mutex_init (&(job->access_mutex)); job->is_live = jobdesc_is_live (job_desc); job->eos = FALSE; job->current_access = 0; job->age = 0; job->last_start_time = NULL; if (job_initialize (job, gstreamill->daemon) != 0) { p = g_strdup_printf ("{\n \"result\": \"failure\",\n \"reason\": \"initialize job failure\"\n}"); g_object_unref (job); return p; } if (job->is_live && (job_output_initialize (job) != 0)) { p = g_strdup_printf ("{\n \"result\": \"failure\",\n \"reason\": \"initialize job output failure\"\n}"); g_object_unref (job); return p; } /* reset and start job */ job_reset (job); if (gstreamill->daemon) { guint64 stat; stat = create_job_process (job); if (stat == JOB_STATE_PLAYING) { GST_ERROR ("Start job %s success", job->name); g_mutex_lock (&(gstreamill->job_list_mutex)); gstreamill->job_list = g_slist_append (gstreamill->job_list, job); g_mutex_unlock (&(gstreamill->job_list_mutex)); p = g_strdup_printf ("{\n \"name\": \"%s\",\n\"result\": \"success\"\n}", job->name); } else { GST_ERROR ("Start job %s failure, return stat: %s", job->name, job_state_get_name (stat)); g_object_unref (job); p = g_strdup_printf ("{\n \"result\": \"failure\",\n \"reason\": \"create process failure\"\n}"); } } else { job_encoders_output_initialize (job); if (job_start (job) == 0) { g_mutex_lock (&(gstreamill->job_list_mutex)); gstreamill->job_list = g_slist_append (gstreamill->job_list, job); g_mutex_unlock (&(gstreamill->job_list_mutex)); p = g_strdup ("{\n \"result\": \"success\"\n}"); } else { p = g_strdup_printf ("{\n \"result\": \"failure\",\n \"reason\": \"unknown\"\n}"); } } return p; }
int main (int argc, char *argv[]) { HTTPMgmt *httpmgmt; HTTPStreaming *httpstreaming; GMainLoop *loop; GOptionContext *ctx; GError *err = NULL; gboolean foreground; struct rlimit rlim; GDateTime *datetime; gchar exe_path[512], *date; ctx = g_option_context_new (NULL); g_option_context_add_main_entries (ctx, options, NULL); g_option_context_add_group (ctx, gst_init_get_option_group ()); if (!g_option_context_parse (ctx, &argc, &argv, &err)) { g_print ("Error initializing: %s\n", GST_STR_NULL (err->message)); exit (1); } g_option_context_free (ctx); GST_DEBUG_CATEGORY_INIT (GSTREAMILL, "gstreamill", 0, "gstreamill log"); if (version) { print_version_info (); exit (0); } /* stop gstreamill. */ if (stop) { gchar *pid_str; gint pid; g_file_get_contents (PID_FILE, &pid_str, NULL, NULL); if (pid_str == NULL) { g_print ("File %s not found, check if gstreamill is running.\n", PID_FILE); exit (1); } pid = atoi (pid_str); g_free (pid_str); g_print ("stoping gstreamill with pid %d ...\n", pid); kill (pid, SIGTERM); exit (0); } /* readlink exe path before setuid, on CentOS, readlink exe path after setgid/setuid failure on permission denied */ memset (exe_path, '\0', sizeof (exe_path)); if (readlink ("/proc/self/exe", exe_path, sizeof (exe_path)) == -1) { g_print ("Read /proc/self/exe error: %s", g_strerror (errno)); exit (2); } if (prepare_gstreamill_run_dir () != 0) { g_print ("Can't create gstreamill run directory\n"); exit (3); } /* if (set_user_and_group () != 0) { g_print ("set user and group failure\n"); exit (4); } */ if (job_file != NULL) { /* gstreamill command with job, run in foreground */ foreground = TRUE; } else { /* gstreamill command without job, run in background */ foreground = FALSE; } if (gst_debug_get_default_threshold () < GST_LEVEL_WARNING) { gst_debug_set_default_threshold (GST_LEVEL_WARNING); } /* initialize ts segment static plugin */ if (!gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR, "tssegment", "ts segment plugin", ts_segment_plugin_init, "0.1.0", "GPL", "GStreamer", "GStreamer", "http://gstreamer.net/")) { GST_ERROR ("registe tssegment error"); exit (17); } /* subprocess, create_job_process */ if (shm_name != NULL) { gint fd; gchar *job_desc, *p; Job *job; gchar *log_path, *name; gint ret; /* set subprocess maximum of core file */ rlim.rlim_cur = 0; rlim.rlim_max = 0; if (setrlimit (RLIMIT_CORE, &rlim) == -1) { GST_ERROR ("setrlimit error: %s", g_strerror (errno)); } /* read job description from share memory */ job_desc = NULL; fd = shm_open (shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (ftruncate (fd, job_length) == -1) { exit (5); } p = mmap (NULL, job_length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); job_desc = g_strdup (p); if ((job_desc != NULL) && (!jobdesc_is_valid (job_desc))) { exit (6); } /* initialize log */ name = (gchar *)jobdesc_get_name (job_desc); if (!jobdesc_is_live (job_desc)) { gchar *p; p = jobdesc_get_log_path (job_desc); log_path = g_build_filename (p, "gstreamill.log", NULL); g_free (p); } else { log_path = g_build_filename (log_dir, name, "gstreamill.log", NULL); } ret = init_log (log_path); g_free (log_path); if (ret != 0) { exit (7); } /* launch a job. */ datetime = g_date_time_new_now_local (); date = g_date_time_format (datetime, "%b %d %H:%M:%S"); fprintf (_log->log_hd, "\n*** %s : job %s starting ***\n\n", date, name); g_date_time_unref (datetime); g_free (date); job = job_new ("name", name, "job", job_desc, NULL); job->is_live = jobdesc_is_live (job_desc); job->eos = FALSE; loop = g_main_loop_new (NULL, FALSE); GST_INFO ("Initializing job ..."); if (job_initialize (job, TRUE) != 0) { GST_ERROR ("initialize job failure, exit"); exit (8); } GST_INFO ("Initializing job done"); GST_INFO ("Initializing job's encoders output ..."); if (job_encoders_output_initialize (job) != 0) { GST_ERROR ("initialize job encoders' output failure, exit"); exit (8); } GST_INFO ("Initializing job's encoders output done"); GST_INFO ("Starting job ..."); if (job_start (job) != 0) { GST_ERROR ("start livejob failure, exit"); exit (9); } datetime = g_date_time_new_now_local (); date = g_date_time_format (datetime, "%b %d %H:%M:%S"); fprintf (_log->log_hd, "\n*** %s : job %s started ***\n\n", date, name); g_date_time_unref (datetime); g_free (date); g_free (name); g_free (job_desc); signal (SIGPIPE, SIG_IGN); signal (SIGUSR1, sighandler); signal (SIGTERM, stop_job); g_main_loop_run (loop); } else { /* set parent process maximum of core file */ rlim.rlim_cur = RLIM_INFINITY; rlim.rlim_max = RLIM_INFINITY; if (setrlimit (RLIMIT_CORE, &rlim) == -1) { GST_ERROR ("setrlimit error: %s", g_strerror (errno)); } } /* run in background? */ if (!foreground) { gchar *path; gint ret; /* pid file exist? */ if (g_file_test (PID_FILE, G_FILE_TEST_EXISTS)) { g_print ("file %s found, gstreamill already running !!!\n", PID_FILE); exit (10); } /* media directory */ path = g_strdup_printf ("%s/dvr", MEDIA_LOCATION); if (!g_file_test (path, G_FILE_TEST_EXISTS)) { g_printf ("Create DVR directory: %s", path); if (g_mkdir_with_parents (path, 0755) != 0) { g_printf ("Create DVR directory failure: %s", path); } } g_free (path); path = g_strdup_printf ("%s/transcode/in", MEDIA_LOCATION); if (!g_file_test (path, G_FILE_TEST_EXISTS)) { g_printf ("Create transcode directory: %s", path); if (g_mkdir_with_parents (path, 0755) != 0) { g_printf ("Create transcode directory failure: %s", path); } } g_free (path); path = g_strdup_printf ("%s/transcode/out", MEDIA_LOCATION); if (!g_file_test (path, G_FILE_TEST_EXISTS)) { g_printf ("Create transcode directory: %s", path); if (g_mkdir_with_parents (path, 0755) != 0) { g_printf ("Create transcode directory failure: %s", path); } } g_free (path); /* log to file */ path = g_build_filename (log_dir, "gstreamill.log", NULL); ret = init_log (path); g_free (path); if (ret != 0) { g_print ("Init log error, ret %d.\n", ret); exit (11); } /* daemonize */ if (daemon (0, 0) != 0) { fprintf (_log->log_hd, "Failed to daemonize"); remove_pid_file (); exit (1); } /* create pid file */ if (create_pid_file () != 0) { exit (1); } /* customize signal */ signal (SIGUSR1, sighandler); signal (SIGTERM, stop_gstreamill); datetime = g_date_time_new_now_local (); date = g_date_time_format (datetime, "%b %d %H:%M:%S"); fprintf (_log->log_hd, "\n*** %s : gstreamill started ***\n\n", date); g_free (date); g_date_time_unref (datetime); } /* ignore SIGPIPE */ signal (SIGPIPE, SIG_IGN); loop = g_main_loop_new (NULL, FALSE); /* gstreamill */ gstreamill = gstreamill_new ("daemon", !foreground, "log_dir", log_dir, "exe_path", exe_path, NULL); if (gstreamill_start (gstreamill) != 0) { GST_ERROR ("start gstreamill error, exit."); remove_pid_file (); exit (12); } /* httpstreaming, pull */ httpstreaming = httpstreaming_new ("gstreamill", gstreamill, "address", http_streaming, NULL); if (httpstreaming_start (httpstreaming, 10) != 0) { GST_ERROR ("start httpstreaming error, exit."); remove_pid_file (); exit (13); } if (!foreground) { /* run in background, management via http */ httpmgmt = httpmgmt_new ("gstreamill", gstreamill, "address", http_mgmt, NULL); if (httpmgmt_start (httpmgmt) != 0) { GST_ERROR ("start http mangment error, exit."); remove_pid_file (); exit (14); } } else { /* run in foreground, start job */ gchar *job, *p, *result; JSON_Value *val; JSON_Object *obj; /* ctrl-c, stop gstreamill */ signal (SIGINT, stop_gstreamill); /* ctrl-\, stop gstreamill */ signal (SIGQUIT, stop_gstreamill); if (!g_file_get_contents (job_file, &job, NULL, NULL)) { GST_ERROR ("Read job file %s error.", job_file); exit (15); } p = gstreamill_job_start (gstreamill, job); val = json_parse_string (p); obj = json_value_get_object (val); result = (gchar *)json_object_get_string (obj, "result"); GST_INFO ("start job result: %s.", result); if (g_strcmp0 (result, "success") != 0) { exit (16); } json_value_free (val); g_free (p); } g_main_loop_run (loop); return 0; }