From: Lukasz Marek <lukasz.m.lu...@gmail.com> 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 | 56 ++++++++++++++++++++++++++++++++++++++++++ libavformat/avio.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++- libavformat/url.h | 3 +++ 3 files changed, 130 insertions(+), 1 deletion(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 4896782..68c7114 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 @@ -418,6 +419,61 @@ int avio_check(const char *url, int flags) return ret; } +int avio_open_dir(void **s, const char *url, AVDictionary **options) +{ + URLContext *h = NULL; + int ret; + av_assert0(s); + if ((ret = ffurl_alloc(&h, url, AVIO_FLAG_READ, NULL)) < 0) + goto fail; + + if (h->prot->url_open_dir && h->prot->url_read_dir && h->prot->url_close_dir) { + if (options && h->prot->priv_data_class && + (ret = av_opt_set_dict(h->priv_data, options)) < 0) + goto fail; + ret = h->prot->url_open_dir(h); + } + else + ret = AVERROR(ENOSYS); + if (ret < 0) + goto fail; + *s = h; + return 0; + + fail: + *s = NULL; + ffurl_close(h); + return ret; +} + +int avio_read_dir(void *s, AVIODirEntry **next) +{ + URLContext *h = s; + int ret; + if ((ret = h->prot->url_read_dir(h, next)) < 0) + avio_free_directory_entry(next); + return ret; +} + +int avio_close_dir(void **s) +{ + URLContext *h; + av_assert0(s); + h = *s; + h->prot->url_close_dir(h); + ffurl_close(h); + *s = NULL; + return 0; +} + +void avio_free_directory_entry(AVIODirEntry **entry) +{ + if (!entry || !*entry) + return; + av_free((*entry)->name); + av_freep(entry); +} + int64_t ffurl_size(URLContext *h) { int64_t pos, size; diff --git a/libavformat/avio.h b/libavformat/avio.h index 8fc7e27..a6fdef1 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -34,7 +34,6 @@ #include "libavformat/version.h" - #define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */ /** @@ -54,6 +53,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. + */ +typedef struct AVIODirEntry { + char *name; /**< Filename */ + 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 +215,42 @@ 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. + * @param options protocol options. + * @return >=0 on success or negative on error. + */ +int avio_open_dir(void **s, const char *url, AVDictionary **options); + +/** + * Get next directory entry. + * + * Returned entry must be freed with avio_free_directory_entry(). + * + * @param s directory read context. + * @param[out] next next entry or NULL when no more entries. + * @return >=0 on success or negative on error. + */ +int avio_read_dir(void *s, AVIODirEntry **next); + +/** + * Close directory. + * + * @param s directory read context. + * @return >=0 on success or negative on error. + */ +int avio_close_dir(void **s); + +/** + * Free entry allocated by avio_read_dir(). + * + * @param entry entry to be freed. + */ +void avio_free_directory_entry(AVIODirEntry **entry); + +/** * 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 d0035f3..2816ac5 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -87,6 +87,9 @@ typedef struct URLProtocol { const AVClass *priv_data_class; int flags; int (*url_check)(URLContext *h, int mask); + int (*url_open_dir)(URLContext *h); + int (*url_read_dir)(URLContext *h, AVIODirEntry **next); + int (*url_close_dir)(URLContext *h); } URLProtocol; /** -- 2.3.3 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel