[FFmpeg-devel] [PATCH] urlconcat protocol

Benoit Fouet benoit.fouet
Tue Jan 26 11:35:18 CET 2010


Hi,

On Tue, 26 Jan 2010 08:01:29 +0100 Michele Orr? wrote:
> HI. As the wiki says, I'm getting throught ffmpeg with a "small and
> interesting patch": the Wolfram Gloger's "fileconcat" protocol.
> I't a simple protocol which let you concat one/more url.
> 
> : http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-June/031256.html
> : http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-July/032121.html
> 
> I tried to follow each single indication, and what i got is in the
> attachment :)
> 
> I've mainly changed how concat.c manages its urls. I don't like at all to
> call realloc() for each time we need to append another url. Then, the old
> uifo struct had two ints, one for the length (yes, repeated for each node)
> and another for the index of the node.  MIne insted has two pointers, one
> for the previous url, and another for the next, so the final size shuoldn't
> change.
> 
> All this aims to a better management of memory, and improve errors handling.
> 

> Index: libavformat/concat.c
> ===================================================================
> --- libavformat/concat.c	(revisione 0)
> +++ libavformat/concat.c	(revisione 0)
> @@ -0,0 +1,189 @@
[...]
> +static int urlconcat_open(URLContext *h, const char *filename, int flags)
> +{
> +    char *fn = NULL;
> +    int64_t size;
> +    size_t len;
> +    URLContext *uc;
> +
> +    struct urlconcat_data *udata = av_malloc(sizeof(struct urlconcat_data));
> +    struct urlconcat_info *uinfo = av_malloc(sizeof(struct urlconcat_info));

sizeof(*udata) and sizeof(*uinfo)

> +    if (!udata || !uinfo) 
> +        return AVERROR(ENOMEM);

this is leaky if udata is not NULL

> +    h->priv_data = udata;
> +    udata->current = udata->begin = uinfo;
> +
> +    av_strstart(filename, "cat:", &filename);
> +    
> +    if   (!*filename) 
> +        return AVERROR(ENOENT);

you're leaking udata and uinfo memory here (and BTW, every return
AVERROR(...) is leaky in this function)

> +    while (*filename) {
> +        /* parsing filename */
> +        for (len = 0; filename[len] && filename[len] != AV_CAT_SEPARATOR; ++len);
> +        fn = av_realloc(fn, sizeof(char) * len);

you can remove the sizeof(char)

> +        if (!fn)
> +            return AVERROR(ENOMEM);
> +        av_strlcpy(fn, filename, len+1);
> +        filename += len;
> +        while (*filename) ++filename;
> +        /* creating URLContext */
> +        if (url_open(&uc, fn, flags) < 0)
> +            return AVERROR(ENOENT);
> +        /* creating size */
> +        size = url_filesize(uc);
> +        if (size < 0)
> +            return AVERROR(ENOSYS);
> +        /* assembling */
> +        uinfo->uc   = uc;
> +        uinfo->size = size;
> +
> +        uinfo->nexturl = av_malloc(sizeof(struct urlconcat_info));
> +        if (!uinfo->nexturl)
> +            return AVERROR(ENOMEM);
> +        uinfo->nexturl->prevurl = uinfo;
> +        uinfo = uinfo->nexturl;
> +    }
> +    /* switching back to previous url (last node),  *
> +     * and connecting to the beginning of the list. */
> +    uinfo = uinfo->prevurl;
> +    av_freep(&fn);

av_free(fn) should be enough

> +    av_freep(&uinfo->nexturl);
> +    
> +    uinfo->nexturl = udata->begin;
> +    udata->begin->prevurl = uinfo;
> +    return 0;
> +}
> +
> +static int urlconcat_read(URLContext *h, unsigned char *buf, int size)
> +{
> +    int result, total = 0;
> +    struct urlconcat_data *udata = h->priv_data;
> +    struct urlconcat_info *uinfo = udata->current,
> +                          *uend  = udata->begin->prevurl;
> +    while (size > 0) {
> +        result = url_read(uinfo->uc, buf, size);
> +        if (result < 0) 
> +            return result;
> +        else if (result == 0) {
> +            if (uinfo == uend) 
> +                break;
> +            uinfo = uinfo->nexturl;
> +            if (url_seek(uinfo->uc, 0, SEEK_SET) < 0) 
> +                break;
> +        } else {
> +        total += result;
> +        buf   += result;
> +        size  -= result;

indentation

> +        }
> +    }
> +    udata->current = uinfo;
> +    return total;
> +}
> +
[...]
> +static int urlconcat_close(URLContext *h)
> +{
> +    int res = 0;
> +    struct urlconcat_data *udata = h->priv_data;
> +    struct urlconcat_info *uinfo = udata->begin->nexturl;
> +
> +    if (udata) {

this check is happening a bit too late; you already dereferenced udata
above

> +        while (uinfo != udata->begin) {
> +            res |= url_close(uinfo->prevurl->uc);
> +            uinfo = uinfo->nexturl;
> +            av_free(uinfo->prevurl);
> +        } 
> +        av_freep(&h->priv_data);
> +    }
> +    return res < 0 ? AVERROR(EIO) : 0;
> +}
> +

Ben



More information about the ffmpeg-devel mailing list