[FFmpeg-devel] [PATCH 1/4] lavf: add directory listing API
Lukasz Marek
lukasz.m.luki2 at gmail.com
Sat Jul 12 03:12:12 CEST 2014
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 | 76 +++++++++++++++++++++++++++++++++++++++++++++-
libavformat/avio.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
libavformat/url.h | 55 ++++++++++++++++++++++++++++++++++
3 files changed, 217 insertions(+), 2 deletions(-)
diff --git a/libavformat/avio.c b/libavformat/avio.c
index 0a2a0a9..021ffc3 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -23,12 +23,14 @@
#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
#include "network.h"
#endif
#include "url.h"
+#include "avio_internal.h"
static URLProtocol *first_protocol = NULL;
@@ -286,6 +288,45 @@ fail:
return ret;
}
+void ffurl_close_dir(URLContext *s)
+{
+ if (s) {
+ if (s->prot->url_close_dir)
+ s->prot->url_close_dir(s);
+ ffurl_close(s);
+ }
+}
+
+int ffurl_open_dir(URLContext **s, const char *url,
+ const AVIOInterruptCB *int_cb, AVDictionary **options)
+{
+ int ret;
+
+ if ((ret = ffurl_alloc(s, url, AVIO_FLAG_READ, int_cb)) < 0)
+ return ret;
+ if (!(*s)->prot->url_open_dir || !(*s)->prot->url_read_dir || !(*s)->prot->url_close_dir) {
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+ if ((*s)->prot->priv_data_class &&
+ (ret = av_opt_set_dict((*s)->priv_data, options)) < 0)
+ goto fail;
+ if ((ret = av_opt_set_dict(*s, options)) < 0)
+ goto fail;
+ if ((ret = (*s)->prot->url_open_dir(*s)) < 0)
+ goto fail;
+ return 0;
+ fail:
+ ffurl_close_dir(*s);
+ *s = NULL;
+ return ret;
+}
+
+int ffurl_next_dir_entry(URLContext *s, const AVIODirEntry **next)
+{
+ return s->prot->url_read_dir(s, next);
+}
+
static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
int size, int size_min,
int (*transfer_func)(URLContext *h,
@@ -389,7 +430,6 @@ int ffurl_close(URLContext *h)
return ffurl_closep(&h);
}
-
const char *avio_find_protocol_name(const char *url)
{
URLProtocol *p = url_find_protocol(url);
@@ -416,6 +456,40 @@ int avio_check(const char *url, int flags)
return ret;
}
+void avio_close_dir(AVIOContext *s)
+{
+ if (s) {
+ ffurl_close_dir(s->opaque);
+ av_free(s);
+ }
+}
+
+int avio_open_dir(AVIOContext **s, const char *url,
+ const AVIOInterruptCB *int_cb, AVDictionary **options)
+{
+ URLContext *h;
+ int ret;
+ av_assert0(s);
+ if ((ret = ffurl_open_dir(&h, url, int_cb, options)) < 0)
+ return ret;
+
+ *s = avio_alloc_context(NULL, 0, h->flags, h, NULL, NULL, NULL);
+ if (!*s) {
+ avio_close_dir(*s);
+ return AVERROR(ENOMEM);
+ }
+ if (h->prot) {
+ (*s)->next_dir_entry = (int(*)(void *, const AVIODirEntry**))h->prot->url_read_dir;
+ }
+ (*s)->av_class = &ffio_url_class;
+ return 0;
+}
+
+int avio_read_dir(AVIOContext *s, AVIODirEntry const **next)
+{
+ return ffurl_next_dir_entry(s->opaque, next);
+}
+
int64_t ffurl_size(URLContext *h)
{
int64_t pos, size;
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 4004b6f..20fd32b 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.
+ * The other fields are protocol or/and platform dependent and might be unknown.
+ */
+typedef struct AVIODirEntry {
+ char *name; /**< Filename without a path. */
+ 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 the owner. */
+ uint32_t group_id; /**< Group ID of the 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
@@ -153,6 +187,13 @@ typedef struct AVIOContext {
* This field is internal to libavformat and access from outside is not allowed.
*/
int orig_buffer_size;
+
+ /**
+ * Get next directory entry.
+ * Returns next directory entry or NULL when more entries. Returned
+ * entry must be valid until next call of AVIOContext.next_dir_entry().
+ */
+ int (*next_dir_entry)(void *opaque, AVIODirEntry const **next);
} AVIOContext;
/* unbuffered I/O */
@@ -181,6 +222,51 @@ const char *avio_find_protocol_name(const char *url);
int avio_check(const char *url, int flags);
/**
+ * Open directory for reading.
+ *
+ * @warning Context created this way cannot be used for I/O operation other than
+ * avio_read_dir() and avio_close_dir().
+ *
+ * @param s directory read context. Pointer to a NULL pointer must be passed.
+ * @param url url of the directory to be listed. It can contain a protocol prefix
+ * like "ftp://", "sftp://" etc. When no protocol prefix is provided
+ * then url is treated as path to a directory on local filesystem.
+ * @param int_cb an interrupt callback to be used at the protocols level
+ * @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. Specific errors:
+ * AVERROR(ENOSYS) - not implemented by protocol.
+ * AVERROR(EINVAL) - invalid URL.
+ * AVERROR(ENOTDIR) - URL is not a directory.
+ * AVERROR(EACCES) - no access to the directory.
+ */
+int avio_open_dir(AVIOContext **s, const char *url,
+ const AVIOInterruptCB *int_cb, 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(AVIOContext *s, AVIODirEntry const **next);
+
+/**
+ * Close directory.
+ *
+ * All resources are freed and context cannot be used anymore.
+ *
+ * @param s directory read context to be closed.
+ */
+void avio_close_dir(AVIOContext *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..4c9c197 100644
--- a/libavformat/url.h
+++ b/libavformat/url.h
@@ -89,6 +89,23 @@ typedef struct URLProtocol {
const AVClass *priv_data_class;
int flags;
int (*url_check)(URLContext *h, int mask);
+ /**
+ * Open directory for reading.
+ * Allocates all resources required by directory listing routine.
+ * It is called once before subsequent url_read_dir calls.
+ */
+ int (*url_open_dir)(URLContext *h);
+ /**
+ * Get next directory entry.
+ * Returns next directory entry or NULL when more entries. Returned
+ * entry must be valid until next call of avio_read_dir() or avio_close_dir().
+ */
+ int (*url_read_dir)(URLContext *h, const AVIODirEntry **next);
+ /**
+ * Close directory.
+ * Releases all resources allocated by url_open_dir and url_read_dir.
+ */
+ void (*url_close_dir)(URLContext *h);
} URLProtocol;
/**
@@ -282,5 +299,43 @@ int ff_url_join(char *str, int size, const char *proto,
void ff_make_absolute_url(char *buf, int size, const char *base,
const char *rel);
+/**
+ * Open directory for reading.
+ *
+ * @param s directory read context. Pointer to a NULL pointer must be passed.
+ * @param url url of the directory to be listed. It can contain a protocol prefix
+ * like "ftp://", "sftp://" etc. When no protocol prefix is provided
+ * then url is treated as path to a directory on local filesystem.
+ * @param int_cb an interrupt callback to be used at the protocols level
+ * @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.
+ */
+int ffurl_open_dir(URLContext **s, const char *url,
+ const AVIOInterruptCB *int_cb, 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 ffurl_next_dir_entry(URLContext *s, const AVIODirEntry **next);
+
+/**
+ * Close directory.
+ *
+ * All resources are freed and context cannot be used anymore.
+ *
+ * @param s directory read context to be closed.
+ */
+void ffurl_close_dir(URLContext *s);
+
#endif /* AVFORMAT_URL_H */
--
1.9.1
More information about the ffmpeg-devel
mailing list