static void dvr_record_segment (EncoderOutput *encoder_output, GstClockTime duration) { gchar *path; gint64 realtime; guint64 rap_addr; gsize segment_size; gchar *buf; GError *err = NULL; /* seek gop it's timestamp is m3u8_push_request->timestamp */ sem_wait (encoder_output->semaphore); rap_addr = encoder_output_gop_seek (encoder_output, encoder_output->last_timestamp); sem_post (encoder_output->semaphore); /* gop not found? */ if (rap_addr == G_MAXUINT64) { GST_ERROR ("Segment not found!"); return; } segment_size = encoder_output_gop_size (encoder_output, rap_addr); buf = g_malloc (segment_size); /* copy segment to buf */ if (rap_addr + segment_size + 12 < encoder_output->cache_size) { memcpy (buf, encoder_output->cache_addr + rap_addr + 12, segment_size); } else { gint n; gchar *p; n = encoder_output->cache_size - rap_addr - 12; p = buf; memcpy (p, encoder_output->cache_addr + rap_addr + 12, n); p += n; memcpy (p, encoder_output->cache_addr, segment_size - n); } realtime = g_get_real_time (); path = g_strdup_printf ("/%s/%ld_%lu_%lu.ts", encoder_output->record_path, realtime, encoder_output->sequence, duration); encoder_output->sequence += 1; if (!g_file_set_contents (path, buf, segment_size, &err)) { GST_ERROR ("write segment %s failure: %s", path, err->message); g_error_free (err); } else { GST_INFO ("write segment %s success", path); } g_free (path); g_free (buf); }
static gsize get_mpeg2ts_segment (RequestData *request_data, EncoderOutput *encoder_output, gchar **buf) { GstClockTime timestamp; gchar *header, *path, *file; guint64 rap_addr; gsize buf_size; GError *err = NULL; /* dvr segment */ if (g_str_has_prefix (request_data->uri, "/dvr/")) { file = g_path_get_basename (request_data->uri); path = g_strdup_printf ("%s/%s", encoder_output->record_path, file); g_free (file); if (!g_file_get_contents (path, &file, &buf_size, &err)) { GST_WARNING ("read %s failure: %s", path, err->message); g_free (path); g_error_free (err); return 0; } header = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "video/mpeg", buf_size, CACHE_60s, ""); *buf = g_malloc (buf_size + strlen (header)); memcpy (*buf, header, strlen (header)); memcpy (*buf + strlen (header), file, buf_size); g_free (header); g_free (file); return buf_size; } /* live segment */ sscanf (request_data->uri, "/live/%*[^/]/encoder/%*[^/]/%lu.ts", ×tamp); if (sem_wait (encoder_output->semaphore) == -1) { GST_WARNING ("get_mpeg2ts_segment sem_wait failure: %s", g_strerror (errno)); return 0; } /* seek gop */ rap_addr = encoder_output_gop_seek (encoder_output, timestamp); if (rap_addr != G_MAXUINT64) { /* segment found, send it */ gsize gop_size; gop_size = encoder_output_gop_size (encoder_output, rap_addr); header = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "video/mpeg", gop_size, CACHE_60s, ""); *buf = g_malloc (strlen (header) + gop_size); memcpy (*buf, header, strlen(header)); if (rap_addr + gop_size + 12 < encoder_output->cache_size) { memcpy (*buf + strlen (header), encoder_output->cache_addr + rap_addr + 12, gop_size); } else { gint n; n = encoder_output->cache_size - rap_addr - 12; memcpy (*buf + strlen (header), encoder_output->cache_addr + rap_addr + 12, n); memcpy (*buf + strlen (header) + n, encoder_output->cache_addr, gop_size - n); } buf_size = strlen (header) + gop_size; g_free (header); } else { /* segment not found */ GST_WARNING ("segment not found: %s", request_data->uri); *buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION); buf_size = strlen (*buf); } sem_post (encoder_output->semaphore); return buf_size; }
static gsize get_mpeg2ts_segment (RequestData *request_data, EncoderOutput *encoder_output, gchar **buf) { GstClockTime timestamp; gint number; guint64 year, month, mday, hour, sequence, duration, rap_addr, max_age; GstClockTime us; /* microseconds */ struct tm tm; gchar date[20], *header, *path, *file, *cache_control; gsize buf_size; GError *err = NULL; struct timespec ts; number = sscanf (request_data->uri, "/%*[^/]/encoder/%*[^/]/%04lu%02lu%02lu%02lu/%lu_%lu_%lu.ts$", &year, &month, &mday, &hour, &us, &sequence, &duration); if (number != 7) { GST_WARNING ("uri not found: %s", request_data->uri); *buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION); buf_size = strlen (*buf); return buf_size; } sprintf (date, "%04lu-%02lu-%02lu %02lu:00:00", year, month, mday, hour); memset (&tm, 0, sizeof (struct tm)); strptime (date, "%Y-%m-%d %H:%M:%S", &tm); tm.tm_isdst = daylight; timestamp = mktime (&tm) * 1000000 + us; /* read from memory */ if (clock_gettime (CLOCK_REALTIME, &ts) == -1) { GST_ERROR ("get_mpeg2ts_segment clock_gettime error: %s", g_strerror (errno)); *buf = g_strdup_printf (http_500, PACKAGE_NAME, PACKAGE_VERSION); buf_size = strlen (*buf); return buf_size; } ts.tv_sec += 2; while (sem_timedwait (encoder_output->semaphore, &ts) == -1) { if (errno == EINTR) { continue; } GST_ERROR ("get_mpeg2ts_segment sem_timedwait failure: %s", g_strerror (errno)); *buf = g_strdup_printf (http_500, PACKAGE_NAME, PACKAGE_VERSION); buf_size = strlen (*buf); return buf_size; } /* seek gop */ rap_addr = encoder_output_gop_seek (encoder_output, timestamp); if (rap_addr != G_MAXUINT64) { /* segment found, send it */ gsize gop_size; gop_size = encoder_output_gop_size (encoder_output, rap_addr); cache_control = g_strdup_printf ("max-age=%lu", encoder_output->dvr_duration); header = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "video/mpeg", gop_size, cache_control, ""); g_free (cache_control); *buf = g_malloc (strlen (header) + gop_size); memcpy (*buf, header, strlen(header)); if (rap_addr + gop_size + 12 < encoder_output->cache_size) { memcpy (*buf + strlen (header), encoder_output->cache_addr + rap_addr + 12, gop_size); } else { gint n; n = encoder_output->cache_size - rap_addr - 12; if (n > 0) { memcpy (*buf + strlen (header), encoder_output->cache_addr + rap_addr + 12, n); memcpy (*buf + strlen (header) + n, encoder_output->cache_addr, gop_size - n); } else { GST_WARNING ("nnnnn: n < 0 %d", n); memcpy (*buf + strlen (header), encoder_output->cache_addr - n, gop_size); } } buf_size = strlen (header) + gop_size; g_free (header); } else { buf_size = 0; } sem_post (encoder_output->semaphore); /* buf_size == 0? segment not found in memory, read frome dvr directory */ if (buf_size == 0) { path = g_strdup_printf ("%s/%04lu%02lu%02lu%02lu/%010lu_%lu_%lu.ts", encoder_output->record_path, year, month, mday, hour, us, sequence, duration); if (!g_file_get_contents (path, &file, &buf_size, &err)) { g_error_free (err); GST_WARNING ("segment not found: %s", request_data->uri); *buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION); buf_size = strlen (*buf); } else { max_age = encoder_output->dvr_duration - (g_get_real_time () - timestamp) / 1000000; cache_control = g_strdup_printf ("max-age=%lu", max_age); header = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "video/mpeg", buf_size, cache_control, ""); g_free (cache_control); *buf = g_malloc (buf_size + strlen (header)); memcpy (*buf, header, strlen (header)); memcpy (*buf + strlen (header), file, buf_size); buf_size += strlen (header); g_free (header); g_free (file); } g_free (path); } return buf_size; }