[FFmpeg-devel] [PATCH 1/6] lavf: add directory listing API
wm4
nfxjfg at googlemail.com
Mon Jul 7 23:59:36 CEST 2014
On Mon, 07 Jul 2014 22:40:57 +0200
Lukasz Marek <lukasz.m.luki2 at gmail.com> wrote:
> From ef6993758b5d361fc878d84657286f6c954b434b Mon Sep 17 00:00:00 2001
> From: Lukasz Marek <lukasz.m.luki2 at gmail.com>
> Date: Sat, 5 Jul 2014 18:11:59 +0200
> Subject: [PATCH 1/6] lavf: add directory listing API
>
> TODO: bump minor, update doc/APIchanges
>
> API allows protocol implementations to provide API that
> allows to list directory content.
> API is similar to POSIX opendir/readdir/closedir.
>
> Signed-off-by: Lukasz Marek <lukasz.m.luki2 at gmail.com>
> ---
> libavformat/avio.c | 38 ++++++++++++++++++++++++++++++
> libavformat/avio.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> libavformat/url.h | 12 ++++++++++
> 3 files changed, 118 insertions(+)
>
> diff --git a/libavformat/avio.c b/libavformat/avio.c
> index 0a2a0a9..f105292 100644
> --- a/libavformat/avio.c
> +++ b/libavformat/avio.c
> @@ -23,6 +23,7 @@
> #include "libavutil/dict.h"
> #include "libavutil/opt.h"
> #include "libavutil/time.h"
> +#include "libavutil/avassert.h"
> #include "os_support.h"
> #include "avformat.h"
> #if CONFIG_NETWORK
> @@ -416,6 +417,43 @@ int avio_check(const char *url, int flags)
> return ret;
> }
>
> +void avio_close_dir(URLContext *s)
> +{
> + if (s) {
> + s->prot->url_close_dir(s);
> + ffurl_close(s);
> + }
> +}
> +
> +int avio_open_dir(URLContext **s, const char *url, AVDictionary **options)
> +{
> + int ret;
> + av_assert0(s);
> + if ((ret = ffurl_alloc(s, url, AVIO_FLAG_READ, NULL)) < 0)
> + goto fail;
> +
> + if ((*s)->prot->url_open_dir && (*s)->prot->url_read_dir && (*s)->prot->url_close_dir) {
> + if (options && (*s)->prot->priv_data_class &&
> + (ret = av_opt_set_dict((*s)->priv_data, options)) < 0)
> + goto fail;
> + ret = (*s)->prot->url_open_dir(*s);
> + }
> + else
> + ret = AVERROR(ENOSYS);
> + if (ret < 0)
> + goto fail;
> + return 0;
> + fail:
> + avio_close_dir(*s);
> + *s = NULL;
> + return ret;
> +}
> +
> +int avio_read_dir(URLContext *s, AVIODirEntry const **next)
> +{
> + return s->prot->url_read_dir(s, next);
> +}
> +
> int64_t ffurl_size(URLContext *h)
> {
> int64_t pos, size;
> diff --git a/libavformat/avio.h b/libavformat/avio.h
> index 4004b6f..0d2e9b8 100644
> --- a/libavformat/avio.h
> +++ b/libavformat/avio.h
> @@ -34,6 +34,7 @@
>
> #include "libavformat/version.h"
>
> +struct URLContext;
All symbols in public headers should have the AV prefix. (I guess this
is why you wanted to use void* as context at first?) I'm not sure how
exactly to fix this, though.
>
> #define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */
>
> @@ -54,6 +55,41 @@ typedef struct AVIOInterruptCB {
> } AVIOInterruptCB;
>
> /**
> + * Directory entry types.
> + */
> +enum AVIODirEntryType {
> + AVIO_ENTRY_UNKNOWN,
> + AVIO_ENTRY_BLOCK_DEVICE,
> + AVIO_ENTRY_CHARACTER_DEVICE,
> + AVIO_ENTRY_DIRECTORY,
> + AVIO_ENTRY_NAMED_PIPE,
> + AVIO_ENTRY_SYMBOLIC_LINK,
> + AVIO_ENTRY_SOCKET,
> + AVIO_ENTRY_FILE
> +};
> +
> +/**
> + * Describes single entry of the directory.
> + *
> + * Only name and type fileds are guaranteed be set.
> + * Rest of fields are protocol or/and platform dependent and might be unknown.
Maybe "The other fields...".
> + */
> +typedef struct AVIODirEntry {
> + char *name; /**< Filename */
Filename with or without path? (I'd expect without path, i.e. strictly
without any '/' characters.)
> + int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.
> + Name can be encoded with UTF-8 eventhough 0 is set.
> + Encoding might be unknown. */
> + enum AVIODirEntryType type; /**< Type of the entry */
> + int64_t size; /**< File size in bytes */
> + int64_t modification_timestamp; /**< Time of last modification in microseconds since unix epoch */
> + int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch */
> + int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix epoch */
> + uint32_t user_id; /**< User ID of owner */
> + uint32_t group_id; /**< Group ID of owner */
> + uint32_t filemode; /**< Unix file mode */
> +} AVIODirEntry;
> +
> +/**
> * Bytestream IO Context.
> * New fields can be added to the end with minor version bumps.
> * Removal, reordering and changes to existing fields require a major
> @@ -181,6 +217,38 @@ const char *avio_find_protocol_name(const char *url);
> int avio_check(const char *url, int flags);
>
> /**
> + * Open directory for reading.
> + *
> + * @param s directory read context. Pointer to a NULL pointer must be passed.
> + * @param url directory to be listed.
Maybe document that it behaves in the same way as URLs passed to
avio_open (or whatever that function was called). So protocol prefixes
are respected etc..
> + * @param options an AVDictionary filled with protocol-private options.
> + * On return this parameter will be destroyed and replaced with a dict
> + * containing options that were not found. May be NULL.
> + * See protocol's documentation to get list valid options.
> + * @return >=0 on success or negative on error.
Document what errors can happen. IMO this is semi-important, because
the user definitely needs to be able to distinguish between not found,
not listable, not implemented, and such. The user shouldn't have to
guess the error codes.
> + */
> +int avio_open_dir(struct URLContext **s, const char *url, AVDictionary **options);
> +
> +/**
> + * Get next directory entry.
> + *
> + * @note This function doesn't return current directory "." nor parent directory "..".
> + *
> + * @param s directory read context.
> + * @param[out] next next entry or NULL when no more entries. Returned entry is
> + * valid until next call of avio_read_dir() or avio_close_dir().
> + * @return >=0 on success or negative on error.
> + */
> +int avio_read_dir(struct URLContext *s, AVIODirEntry const **next);
> +
> +/**
> + * Close directory.
> + *
> + * @param s directory read context to be closed.
Maybe I'm too pedantic here, but maybe document that s is actually
free'd.
> + */
> +void avio_close_dir(struct URLContext *s);
> +
> +/**
> * Allocate and initialize an AVIOContext for buffered I/O. It must be later
> * freed with av_free().
> *
> diff --git a/libavformat/url.h b/libavformat/url.h
> index 712ea0f..8e0dd9d 100644
> --- a/libavformat/url.h
> +++ b/libavformat/url.h
> @@ -89,6 +89,18 @@ typedef struct URLProtocol {
> const AVClass *priv_data_class;
> int flags;
> int (*url_check)(URLContext *h, int mask);
> + /**
> + * Open directory for reading.
> + */
That's a bit unspecific. The implementer would have to read the source
code using this function to understand how to implement this. But maybe
I'm a bit too pedantic again.
> + int (*url_open_dir)(URLContext *h);
> + /**
> + * Get next directory entry.
> + */
> + int (*url_read_dir)(URLContext *h, AVIODirEntry const **next);
> + /**
> + * Close directory.
> + */
> + void (*url_close_dir)(URLContext *h);
> } URLProtocol;
>
> /**
More information about the ffmpeg-devel
mailing list