Le quartidi 24 messidor, an CCXXII, Lukasz Marek a écrit : > 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.lu...@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); > + } > +}
Maybe ffurl_close_dirp(), and use ffurl_closep(). > + > +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); > + } > +} Here and similarly for the other functions: do you think we need the indirection avio_ -> ffurl_? It exist for the current API because the ffurl_ stuff used to be public, but I see no reason to make new code more complex like that. > + > +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" > > - Spurious change. > #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 > +}; Any reason for the order? IMHO, alphabetic would be better, and frequency even better: FILE=0, then DIRECTORY, then the strange Unix stuff. Ans UNKNOWN either last or special with -1. > + > +/** > + * 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. */ const? > + 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. */ What would it be otherwise? > + 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. */ Is there a way of distinguishing unknown values from actual values? > +} 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); I believe the "const" qualifier is supposed to come in front of the type. cdecl, at least, does not like that syntax. > } 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. Please specify whether the return code for EOF is 0 or AVERROR_EOF. > + */ > +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); If these function remain, do they need to be made global to the library? Making them static to the file should be enough. > + > +/** > + * 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 */ Regards, -- Nicolas George
signature.asc
Description: Digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel