[FFmpeg-devel] [PATCH 1/4] ffserver: Implement refcounted segments.

Michael Niedermayer michael at niedermayer.cc
Fri Apr 13 17:08:42 EEST 2018


On Thu, Apr 12, 2018 at 03:35:46PM +0200, Stephan Holljes wrote:
> ---
>  segment.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  segment.h | 104 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 247 insertions(+)
>  create mode 100644 segment.c
>  create mode 100644 segment.h
> 
> diff --git a/segment.c b/segment.c
> new file mode 100644
> index 0000000..0ef58a1
> --- /dev/null
> +++ b/segment.c
> @@ -0,0 +1,143 @@
> +#include <stdio.h>
> +#include "segment.h"
> +#include <pthread.h>
> +
> +#include <libavutil/opt.h>
> +#include <libavutil/log.h>

This and other files lack a license header



> +
> +
> +void save_segment(struct Segment *seg, const char *filename)
> +{
> +    FILE *out = fopen(filename, "w");
> +    fwrite(seg->buf, seg->size, 1, out);
> +    fclose(out);
> +}

probably should use avio from libavformat so as not to limit it to local files


> +
> +void segment_free(struct Segment *seg)
> +{
> +    av_log(NULL, AV_LOG_DEBUG, "Freeing segment\n");
> +    avformat_free_context(seg->fmt_ctx);
> +    av_free(seg->io_ctx->buffer);
> +    av_free(seg->io_ctx);
> +    free(seg->buf);
> +    free(seg->ts);
> +    free(seg);

iam not sure mixing free and av_free is a good idea. its a recipe for disaster



> +}
> +
> +void segment_ref(struct Segment *seg)
> +{
> +    pthread_mutex_lock(&seg->nb_read_lock);
> +    seg->nb_read++;
> +    av_log(NULL, AV_LOG_DEBUG, "  ref Readers: %d\n", seg->nb_read);
> +    pthread_mutex_unlock(&seg->nb_read_lock);
> +}
> +
> +void segment_unref(struct Segment *seg)
> +{
> +    pthread_mutex_lock(&seg->nb_read_lock);
> +    seg->nb_read--;
> +    pthread_mutex_unlock(&seg->nb_read_lock);
> +    av_log(NULL, AV_LOG_DEBUG, "unref Readers: %d\n", seg->nb_read);
> +    if (seg->nb_read == 0) {
> +        segment_free(seg);
> +    }
> +}
> +
> +void segment_ts_append(struct Segment *seg, int64_t dts, int64_t pts)
> +{
> +    seg->ts = (int64_t*) realloc(seg->ts, sizeof(int64_t) * 2  * (seg->ts_len + 2));
> +    seg->ts[seg->ts_len] = dts;
> +    seg->ts[seg->ts_len + 1] = pts;
> +    seg->ts_len += 2;
> +    return;
> +}
> +
> +int segment_write(void *opaque, unsigned char *buf, int buf_size)
> +{
> +    struct Segment *seg = (struct Segment*) opaque;
> +    seg->size += buf_size;
> +    seg->buf = (char*) realloc(seg->buf, seg->size);
> +    memcpy(seg->buf + seg->size - buf_size, buf, buf_size);
> +    return buf_size;
> +}
> +
> +int segment_read(void *opaque, unsigned char *buf, int buf_size)
> +{
> +    struct SegmentReadInfo *info = (struct SegmentReadInfo*) opaque;
> +    buf_size = buf_size < info->left ? buf_size : info->left;
> +
> +    /* copy internal buffer data to buf */
> +    memcpy(buf, info->buf, buf_size);
> +    info->buf  += buf_size;
> +    info->left -= buf_size;
> +    return buf_size ? buf_size : AVERROR_EOF;
> +}
> +
> +
> +void segment_close(struct Segment *seg)
> +{
> +    av_write_trailer(seg->fmt_ctx);
> +}
> +
> +void segment_init(struct Segment **seg_p, AVFormatContext *fmt)
> +{
> +    int ret;
> +    int i;
> +    AVStream *in_stream, *out_stream;
> +    AVCodecContext *codec_ctx;
> +    struct Segment *seg = (struct Segment*) malloc(sizeof(struct Segment));
> +
> +    seg->ifmt = fmt->iformat;
> +    seg->fmt_ctx = NULL;
> +    seg->nb_read = 0;
> +    seg->size = 0;
> +    seg->ts = NULL;
> +    seg->ts_len = 0;
> +    seg->buf = NULL;
> +    seg->avio_buffer = (unsigned char*) av_malloc(AV_BUFSIZE);
> +    pthread_mutex_init(&seg->nb_read_lock, NULL);
> +    seg->io_ctx = avio_alloc_context(seg->avio_buffer, AV_BUFSIZE, 1, seg, NULL, &segment_write, NULL);
> +    seg->io_ctx->seekable = 0;
> +    avformat_alloc_output_context2(&seg->fmt_ctx, NULL, "matroska", NULL);
> +    if ((ret = av_opt_set_int(seg->fmt_ctx, "flush_packets", 1, AV_OPT_SEARCH_CHILDREN)) < 0) {
> +        av_log(NULL, AV_LOG_WARNING, "Could not set flush_packets!\n");
> +    }
> +
> +    seg->fmt_ctx->flags |= AVFMT_FLAG_GENPTS;
> +    seg->fmt_ctx->oformat->flags &= AVFMT_NOFILE;
> +

> +    av_log(NULL, AV_LOG_DEBUG, "Initializing segment\n");

av_log should not be used with a NULL context, as it will make it hard for
the user/developer to identify where a message came from when things become
more complex than a single thread, single client

thanks

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The worst form of inequality is to try to make unequal things equal.
-- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20180413/9c6eb970/attachment.sig>


More information about the ffmpeg-devel mailing list