[FFmpeg-devel] [PATCH] Suggested Patch for "Memory" Protocol

Michel Bardiaux mbardiaux
Wed May 2 17:55:37 CEST 2007


Lagrange Multiplier wrote:
> Greetings,
> 
>     Would the ffmpeg development team consider including the following patch to support a "mem" protocol?  The "mem" protocol simply uses RAM as a source for input multimedia data, akin to how the "file" and "pipe" protocols use filesystem files and pipes as sources.
> 
>     While this patch would be particularly useful for embedded systems (in particular, ones with DSPs that partially or fully encode multimedia data rather than "frame-grabber"-type systems), I'm sure one can see the general applicability as well...  The modifications consist mostly of the addition of libavformat/mem.c, but I've included some C++ compatability wrapping for some of the internal headers as well.
> 
>     Thanks for your time...
> 
>                                                  - LM

Apart from technical remarks below, there is a general problem: most 
embedded systems, and many apps, will *already* have their own 
memory-buffer system, probly incompatible with, and much more developped 
than, the minimal one proposed. I have been using a mem protocol since 
2003, but exactly for that reason I have never proposed it for inclusion.

> ------------------------------------------------------------------------
> 
> diff -Naur before/ffmpeg/libavcodec/opt.h after/ffmpeg/libavcodec/opt.h
> --- before/ffmpeg/libavcodec/opt.h	2007-01-21 07:32:01.000000000 -0500
> +++ after/ffmpeg/libavcodec/opt.h	2007-01-29 09:32:45.000000000 -0500
> @@ -22,6 +22,10 @@
>  #ifndef AVOPT_H
>  #define AVOPT_H
>  
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +

Please remove all these. They are actually irrelevant to the topic, so 
they should be moved to an entirely separate patch.

[snip]

> diff -Naur before/ffmpeg/libavformat/avio.h after/ffmpeg/libavformat/avio.h
> --- before/ffmpeg/libavformat/avio.h	2007-01-14 17:07:19.000000000 -0500
> +++ after/ffmpeg/libavformat/avio.h	2007-01-29 09:15:40.000000000 -0500
> @@ -196,6 +196,18 @@
>  extern URLProtocol file_protocol;
>  extern URLProtocol pipe_protocol;
>  
> +/* mem.c */
> +extern URLProtocol mem_protocol;
> +
> +#define MEMORY_TRANSFER_METHOD "mem:"
> +
> +typedef struct
> +{
> +    char transferMethod[4];
> +    char* buffer;
> +    unsigned int length;
> +} MemoryBufferSpecifier;

This should be strictly private to mem.c, I think.

> +
>  /* udp.c */
>  extern URLProtocol udp_protocol;
>  int udp_set_remote_url(URLContext *h, const char *uri);

[snip]

> diff -Naur before/ffmpeg/libavformat/Makefile after/ffmpeg/libavformat/Makefile
> --- before/ffmpeg/libavformat/Makefile	2007-01-24 19:34:38.000000000 -0500
> +++ after/ffmpeg/libavformat/Makefile	2007-01-29 09:16:16.000000000 -0500
> @@ -159,7 +159,7 @@
>  OBJS+= avio.o aviobuf.o
>  
>  ifeq ($(CONFIG_PROTOCOLS),yes)
> -OBJS+= file.o
> +OBJS+= file.o mem.o
>  ifeq ($(CONFIG_NETWORK),yes)
>  OBJS+= udp.o tcp.o http.o rtsp.o rtp.o rtpproto.o mpegts.o base64.o rtp_h264.o
>  endif
> diff -Naur before/ffmpeg/libavformat/mem.c after/ffmpeg/libavformat/mem.c
> --- before/ffmpeg/libavformat/mem.c	1969-12-31 19:00:00.000000000 -0500
> +++ after/ffmpeg/libavformat/mem.c	2007-01-29 10:11:26.000000000 -0500
> @@ -0,0 +1,161 @@
> +/*
> + * Buffered mem io for ffmpeg system
> + */
> +#include "avformat.h"
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <sys/time.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +
> +#define DEBUG 0
> +
> +typedef struct
> +{
> +    void* which;
> +    char* start;
> +    char* end;
> +    char* last;
> +    int   flags;
> +} MemoryBuffer;
> +
> +static int mem_open(URLContext *h, const char *filename, int flags)
> +{
> +    MemoryBuffer* b = av_malloc(sizeof(MemoryBuffer));
> +    MemoryBufferSpecifier* s = filename;
> +
> +#if DEBUG
> +    fprintf(stderr, "mem_open(%p, %p, %d)\n", h, s->buffer, s->length);
> +#endif

This is NOT the correct way to print info, av_log has to be used.

> +    b->which = h;
> +    b->start = s->buffer;
> +    b->end = &s->buffer[s->length];
> +    b->last = b->start;
> +    b->flags = flags;
> +    h->priv_data = b;
> +    return 0;
> +}
> +
> +static int mem_read(URLContext *h, unsigned char *buf, int size)
> +{
> +    MemoryBuffer* b = (MemoryBuffer*) h->priv_data;
> +    int bytes;
> +
> +    if ((b->flags != URL_RDONLY) && (b->flags != URL_RDWR))
> +    {
> +	errno = EBADF;
> +	return -1;
> +    }
> +    bytes = size;
> +    if (&b->last[bytes] > b->end)
> +    {
> +	bytes = b->end - b->last;
> +    }
> +    memcpy(buf, b->last, bytes);
> +    b->last = &b->last[bytes];
> +#if DEBUG
> +    fprintf(stderr, "%d <- mem_read(%p, %d)\n", bytes, b->which, size);
> +#endif
> +    return bytes;
> +}
> +
> +static int mem_write(URLContext *h, unsigned char *buf, int size)
> +{
> +    MemoryBuffer* b = (MemoryBuffer*) h->priv_data;
> +    int bytes;
> +
> +    if ((b->flags != URL_WRONLY) && (b->flags != URL_RDWR))
> +    {
> +	errno = EBADF;
> +	return -1;
> +    }
> +    bytes = size;
> +    if (&b->last[bytes] > b->end)
> +    {
> +#if DEBUG
> +	fprintf(stderr, "NOSPC <- mem_write(%p, %d) into buffer of %d\n",
> +	       b->which,
> +	       size,
> +	       b->end - b->last);
> +#endif
> +	errno = ENOSPC;
> +	return -1;
> +    }
> +    memcpy(b->last, buf, bytes);
> +    b->last = &b->last[bytes];
> +#if DEBUG
> +    fprintf(stderr, "%d <- mem_write(%p, %d)\n", bytes, b->which, size);
> +#endif
> +    return size;
> +}

With no option to automatically extend the buffer when needed?

> +
> +static offset_t mem_seek(URLContext *h, offset_t pos, int whence)
> +{
> +    MemoryBuffer* b = (MemoryBuffer*) h->priv_data;
> +    char* end;
> +
> +    switch(whence)
> +    {
> +	case SEEK_SET:
> +	    end = &b->start[pos];
> +	    break;
> +	case SEEK_CUR:
> +	    end = &b->last[pos];
> +	    break;
> +	case SEEK_END:
> +	    end = &b->end[pos];
> +	    break;
> +	default:
> +	    errno = EINVAL;
> +	    return -1;
> +    }
> +    if (end < b->start)
> +    {
> +	end = b->start;
> +    }
> +    if (end > b->end)
> +    {
> +	end = b->end;
> +    }
> +    b->last = end;
> +#if DEBUG
> +    fprintf(stderr, "%d <- mem_seek(%p, %lld, %d)\n", b->last - b->start, b->which, pos, whence);
> +#endif
> +    return b->last - b->start;
> +}
> +
> +static int mem_close(URLContext *h)
> +{
> +    MemoryBuffer* b = (MemoryBuffer*) h->priv_data;
> +
> +#if DEBUG
> +    fprintf(stderr, "mem_close(%p, %p/%p/%p)\n", b->which, b->start, b->last, b->end);
> +#endif
> +    av_free(h->priv_data);
> +    return 0;
> +}
> +
> +int mem_replenish(URLContext *h, const char *filename)
> +{
> +    MemoryBuffer* b = (MemoryBuffer*) h->priv_data;
> +    MemoryBufferSpecifier* s = filename;
> +
> +#if DEBUG
> +    fprintf(stderr, "mem_replenish(%p, %p, %d)\n", h, s->buffer, s->length);
> +#endif
> +    b->which = h;
> +    b->start = s->buffer;
> +    b->end = &s->buffer[s->length];
> +    b->last = b->start;
> +    return 0;
> +}

This is the most critical part, how the user fills buffers for ffmpeg, 
or reads from buffers from ffmpeg. No documentation, and deliberately 
unreadable code. If 'filename' is actually a pointer to user data, why 
declare it char* filename instead of void* userdata, for Turing's sake?

> +
> +URLProtocol mem_protocol = {
> +    "mem",
> +    mem_open,
> +    mem_read,
> +    mem_write,
> +    mem_seek,
> +    mem_close,
> +};
> diff -Naur before/ffmpeg/libavutil/common.h after/ffmpeg/libavutil/common.h
> --- before/ffmpeg/libavutil/common.h	2007-01-12 23:01:35.000000000 -0500
> +++ after/ffmpeg/libavutil/common.h	2007-01-29 10:58:55.000000000 -0500
> @@ -23,8 +23,8 @@
>   * common internal and external api header.
>   */
>  
> -#ifndef COMMON_H
> -#define COMMON_H
> +#ifndef FFMPEG_COMMON_H
> +#define FFMPEG_COMMON_H

Separate patch please.

>  
>  #include <inttypes.h>
>  
> @@ -345,4 +345,4 @@
>  char *av_strdup(const char *s);
>  void av_freep(void *ptr);
>  
> -#endif /* COMMON_H */
> +#endif /* FFMPEG_COMMON_H */

-- 
Michel Bardiaux
R&D Director
T +32 [0] 2 790 29 41
F +32 [0] 2 790 29 02
E mailto:mbardiaux at mediaxim.be

Mediaxim NV/SA
Vorstlaan 191 Boulevard du Souverain
Brussel 1160 Bruxelles
http://www.mediaxim.com/




More information about the ffmpeg-devel mailing list