예제 #1
0
파일: job.c 프로젝트: bbshocking/gstreamill
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);
}
예제 #2
0
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", &timestamp);
        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;
}
예제 #3
0
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;
}