/* * job_reset: * @job: job object * * reset job stat * */ void job_reset (Job *job) { gchar *stat, **stats, **cpustats; GstDateTime *start_time; gint i; EncoderOutput *encoder; guint version, window_size; *(job->output->state) = JOB_STATE_VOID_PENDING; g_file_get_contents ("/proc/stat", &stat, NULL, NULL); stats = g_strsplit (stat, "\n", 10); cpustats = g_strsplit (stats[0], " ", 10); job->start_ctime = 0; for (i = 1; i < 8; i++) { job->start_ctime += g_ascii_strtoull (cpustats[i], NULL, 10); } job->last_ctime = 0; job->last_utime = 0; job->last_stime = 0; g_free (stat); g_strfreev (stats); g_strfreev (cpustats); start_time = gst_date_time_new_now_local_time (); if (job->last_start_time != NULL) { g_free (job->last_start_time); } job->last_start_time = gst_date_time_to_iso8601_string (start_time); gst_date_time_unref (start_time); /* is live job with m3u8streaming? */ if (!(job->is_live) || !(jobdesc_m3u8streaming (job->description))) { return; } version = jobdesc_m3u8streaming_version (job->description); if (version == 0) { version = 3; } window_size = jobdesc_m3u8streaming_window_size (job->description); for (i = 0; i < job->output->encoder_count; i++) { encoder = &(job->output->encoders[i]); /* encoder dvr sequence */ encoder->sequence = job->output->sequence; /* reset m3u8 playlist */ if (encoder->m3u8_playlist != NULL) { m3u8playlist_free (encoder->m3u8_playlist); } encoder->m3u8_playlist = m3u8playlist_new (version, window_size, 0); } }
/* * job_output_initialize: * @job: (in): job object * * job output, for client access. * */ gint job_output_initialize (Job *job) { gint i; JobOutput *output; output = job->output; /* m3u8 streaming? */ if (jobdesc_m3u8streaming (job->description)) { /* m3u8 master playlist */ output->master_m3u8_playlist = render_master_m3u8_playlist (job); if (output->master_m3u8_playlist == NULL) { GST_ERROR ("job %s render master m3u8 playlist failure", job->name); return 1; } } else { output->master_m3u8_playlist = NULL; } /* initialize m3u8 and dvr parameters */ for (i = 0; i < output->encoder_count; i++) { output->encoders[i].m3u8_playlist = NULL; output->encoders[i].system_clock = job->system_clock; /* timeshift and dvr */ output->encoders[i].record_path = NULL; output->encoders[i].dvr_duration = jobdesc_dvr_duration (job->description); if (output->encoders[i].dvr_duration == 0) { continue; } output->encoders[i].record_path = g_strdup_printf ("%s/dvr/%s/%d", MEDIA_LOCATION, job->name, i); if (!g_file_test (output->encoders[i].record_path, G_FILE_TEST_EXISTS) && (g_mkdir_with_parents (output->encoders[i].record_path, 0755) != 0)) { GST_ERROR ("Can't open or create %s directory", output->encoders[i].record_path); } } output->sequence = get_dvr_sequence (output); return 0; }
guint encoder_initialize (GArray *earray, gchar *job, EncoderOutput *encoders, Source *source) { gint i, j, k; gchar *job_name, *pipeline; Encoder *encoder; EncoderStream *estream; SourceStream *sstream; gchar **bins; gsize count; job_name = jobdesc_get_name (job); count = jobdesc_encoders_count (job); for (i = 0; i < count; i++) { pipeline = g_strdup_printf ("encoder.%d", i); encoder = encoder_new ("name", pipeline, NULL); encoder->id = i; encoder->last_running_time = GST_CLOCK_TIME_NONE; encoder->output = &(encoders[i]); encoder->segment_duration = jobdesc_m3u8streaming_segment_duration (job); encoder->duration_accumulation = 0; encoder->last_segment_duration = 0; encoder->force_key_count = 0; bins = jobdesc_bins (job, pipeline); if (encoder_extract_streams (encoder, bins) != 0) { GST_ERROR ("extract encoder %s streams failure", encoder->name); g_free (job_name); g_free (pipeline); g_strfreev (bins); return 1; } g_strfreev (bins); for (j = 0; j < encoder->streams->len; j++) { estream = g_array_index (encoder->streams, gpointer, j); estream->state = &(encoders[i].streams[j]); g_strlcpy (encoders[i].streams[j].name, estream->name, STREAM_NAME_LEN); estream->encoder = encoder; estream->source = NULL; for (k = 0; k < source->streams->len; k++) { sstream = g_array_index (source->streams, gpointer, k); if (g_strcmp0 (sstream->name, estream->name) == 0) { estream->source = sstream; estream->current_position = -1; estream->system_clock = encoder->system_clock; g_array_append_val (sstream->encoders, estream); break; } } if (estream->source == NULL) { GST_ERROR ("cant find job %s source %s.", job_name, estream->name); g_free (job_name); g_free (pipeline); return 1; } } /* parse bins and create pipeline. */ encoder->bins = bins_parse (job, pipeline); if (encoder->bins == NULL) { GST_ERROR ("parse job %s bins error", job_name); g_free (job_name); g_free (pipeline); return 1; } complete_request_element (encoder->bins); if (create_encoder_pipeline (encoder) != 0) { GST_ERROR ("create encoder %s pipeline failure", encoder->name); g_free (job_name); g_free (pipeline); return 1; } /* parse udpstreaming */ udpstreaming_parse (job, encoder); /* m3u8 playlist */ if (jobdesc_m3u8streaming (job)) { gchar *mq_name; mq_name = g_strdup_printf ("/%s.%d", job_name, i); encoder->mqdes = mq_open (mq_name, O_WRONLY); if (encoder->mqdes == -1) { g_free (job_name); g_free (pipeline); GST_ERROR ("mq_open %s error: %s", mq_name, g_strerror (errno)); return 1; } g_free (mq_name); } else { encoder->mqdes = -1; } g_free (pipeline); g_array_append_val (earray, encoder); } g_free (job_name); return 0; }
guint encoder_initialize (GArray *earray, gchar *job, EncoderOutput *encoders, Source *source) { gint i, j, k; gchar *job_name, *pipeline; Encoder *encoder; EncoderStream *estream; SourceStream *sstream; gchar **bins; gsize count; job_name = jobdesc_get_name (job); count = jobdesc_encoders_count (job); for (i = 0; i < count; i++) { pipeline = g_strdup_printf ("encoder.%d", i); encoder = encoder_new ("name", pipeline, NULL); encoder->job_name = g_strdup (job_name); encoder->id = i; encoder->last_running_time = GST_CLOCK_TIME_NONE; encoder->output = &(encoders[i]); encoder->segment_duration = jobdesc_m3u8streaming_segment_duration (job); encoder->duration_accumulation = 0; encoder->last_segment_duration = 0; encoder->force_key_count = 0; encoder->has_video = FALSE; encoder->has_audio_only = FALSE; encoder->has_tssegment = FALSE; bins = jobdesc_bins (job, pipeline); if (encoder_extract_streams (encoder, bins) != 0) { GST_ERROR ("extract encoder %s streams failure", encoder->name); g_free (job_name); g_free (pipeline); g_strfreev (bins); return 1; } g_strfreev (bins); for (j = 0; j < encoder->streams->len; j++) { estream = g_array_index (encoder->streams, gpointer, j); estream->state = &(encoders[i].streams[j]); g_strlcpy (encoders[i].streams[j].name, estream->name, STREAM_NAME_LEN); estream->encoder = encoder; estream->source = NULL; for (k = 0; k < source->streams->len; k++) { sstream = g_array_index (source->streams, gpointer, k); if (g_strcmp0 (sstream->name, estream->name) == 0) { estream->source = sstream; estream->current_position = -1; estream->system_clock = encoder->system_clock; g_array_append_val (sstream->encoders, estream); break; } } if (estream->source == NULL) { GST_ERROR ("cant find job %s source %s.", job_name, estream->name); g_free (job_name); g_free (pipeline); return 1; } } /* mkdir for transcode job. */ if (!jobdesc_is_live (job)) { gchar *locations[] = {"%s.elements.filesink.property.location", "%s.elements.hlssink.property.location", NULL}; gchar *p, *value, **location; location = locations; while (*location != NULL) { p = g_strdup_printf (*location, pipeline); value = jobdesc_element_property_value (job, p); g_free (p); if (value != NULL) { break; } location += 1; } if (*location == NULL) { GST_ERROR ("No location found for transcode"); return 1; } p = g_path_get_dirname (value); g_free (value); if (g_mkdir_with_parents (p, 0755) != 0) { GST_ERROR ("Can't open or create directory: %s.", p); g_free (p); return 1; } g_free (p); } /* parse bins and create pipeline. */ encoder->bins = bins_parse (job, pipeline); if (encoder->bins == NULL) { GST_ERROR ("parse job %s bins error", job_name); g_free (job_name); g_free (pipeline); return 1; } complete_request_element (encoder->bins); if (create_encoder_pipeline (encoder) != 0) { GST_ERROR ("create encoder %s pipeline failure", encoder->name); g_free (job_name); g_free (pipeline); return 1; } /* parse udpstreaming */ udpstreaming_parse (job, encoder); /* m3u8 playlist */ encoder->is_first_key = TRUE; if (jobdesc_m3u8streaming (job)) { memset (&(encoder->msg_sock_addr), 0, sizeof (struct sockaddr_un)); encoder->msg_sock_addr.sun_family = AF_UNIX; strncpy (encoder->msg_sock_addr.sun_path, MSG_SOCK_PATH, sizeof (encoder->msg_sock_addr.sun_path) - 1); encoder->msg_sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0); encoder->has_m3u8_output = TRUE; } else { encoder->has_m3u8_output = FALSE; } g_free (pipeline); g_array_append_val (earray, encoder); } g_free (job_name); return 0; }
/* * job_reset: * @job: job object * * reset job stat * */ void job_reset (Job *job) { gchar *stat, **stats, **cpustats; GstDateTime *start_time; gint i; EncoderOutput *encoder; guint version, window_size; struct sigevent sev; struct mq_attr attr; gchar *name; g_file_get_contents ("/proc/stat", &stat, NULL, NULL); stats = g_strsplit (stat, "\n", 10); cpustats = g_strsplit (stats[0], " ", 10); job->start_ctime = 0; for (i = 1; i < 8; i++) { job->start_ctime += g_ascii_strtoull (cpustats[i], NULL, 10); } job->last_ctime = 0; job->last_utime = 0; job->last_stime = 0; g_free (stat); g_strfreev (stats); g_strfreev (cpustats); start_time = gst_date_time_new_now_local_time (); if (job->last_start_time != NULL) { g_free (job->last_start_time); } job->last_start_time = gst_date_time_to_iso8601_string (start_time); gst_date_time_unref (start_time); /* is live job with m3u8streaming? */ if (!(job->is_live) || !(jobdesc_m3u8streaming (job->description))) { return; } version = jobdesc_m3u8streaming_version (job->description); if (version == 0) { version = 3; } window_size = jobdesc_m3u8streaming_window_size (job->description); for (i = 0; i < job->output->encoder_count; i++) { encoder = &(job->output->encoders[i]); name = g_strdup_printf ("/%s.%d", job->name, i); /* encoder dvr sequence */ encoder->sequence = job->output->sequence; /* reset m3u8 playlist */ if (encoder->m3u8_playlist != NULL) { m3u8playlist_free (encoder->m3u8_playlist); } encoder->m3u8_playlist = m3u8playlist_new (version, window_size, 0); /* reset message queue */ if (encoder->mqdes != -1) { if (mq_close (encoder->mqdes) == -1) { GST_ERROR ("mq_close %s error: %s", name, g_strerror (errno)); } if (mq_unlink (name) == -1) { GST_ERROR ("mq_unlink %s error: %s", name, g_strerror (errno)); } } attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = 128; attr.mq_curmsgs = 0; encoder->mqdes = mq_open (name, O_RDONLY | O_CREAT | O_NONBLOCK, 0666, &attr); if (encoder->mqdes == -1) { GST_ERROR ("mq_open error : %s", g_strerror (errno)); } sev.sigev_notify = SIGEV_THREAD; sev.sigev_notify_function = notify_function; sev.sigev_notify_attributes = NULL; sev.sigev_value.sival_ptr = encoder; if (mq_notify (encoder->mqdes, &sev) == -1) { GST_ERROR ("mq_notify error : %s", g_strerror (errno)); } g_free (name); } }