Skip to content

Commit

Permalink
lavf: add directory listing API
Browse files Browse the repository at this point in the history
API allows protocol implementations to provide API that
allows to list directory content.
API is similar to POSIX opendir/readdir/closedir.

Signed-off-by: Michael Niedermayer <[email protected]>
  • Loading branch information
Lukasz Marek authored and michaelni committed Mar 27, 2015
1 parent dbce8cd commit 184084c
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 1 deletion.
74 changes: 74 additions & 0 deletions libavformat/avio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -418,6 +419,79 @@ int avio_check(const char *url, int flags)
return ret;
}

int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options)
{
URLContext *h = NULL;
AVIODirContext *ctx = NULL;
int ret;
av_assert0(s);

ctx = av_mallocz(sizeof(*ctx));
if (!ctx) {
ret = AVERROR(ENOMEM);
goto fail;
}

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;

ctx->url_context = h;
*s = ctx;
return 0;

fail:
av_free(ctx);
*s = NULL;
ffurl_close(h);
return ret;
}

int avio_read_dir(AVIODirContext *s, AVIODirEntry **next)
{
URLContext *h;
int ret;

if (!s || !s->url_context)
return AVERROR(EINVAL);
h = s->url_context;
if ((ret = h->prot->url_read_dir(h, next)) < 0)
avio_free_directory_entry(next);
return ret;
}

int avio_close_dir(AVIODirContext **s)
{
URLContext *h;

av_assert0(s);
if (!(*s) || !(*s)->url_context)
return AVERROR(EINVAL);
h = (*s)->url_context;
h->prot->url_close_dir(h);
ffurl_close(h);
av_freep(s);
*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;
Expand Down
84 changes: 83 additions & 1 deletion libavformat/avio.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

#include "libavformat/version.h"


#define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */

/**
Expand All @@ -53,6 +52,47 @@ typedef struct AVIOInterruptCB {
void *opaque;
} 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 fields are guaranteed be set.
* Rest of fields are protocol or/and platform dependent and might be unknown.
*/
typedef struct AVIODirEntry {
char *name; /**< Filename */
int type; /**< Type of the entry */
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. */
int64_t size; /**< File size in bytes, -1 if unknown. */
int64_t modification_timestamp; /**< Time of last modification in microseconds since unix
epoch, -1 if unknown. */
int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch,
-1 if unknown. */
int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix
epoch, -1 if unknown. */
int64_t user_id; /**< User ID of owner, -1 if unknown. */
int64_t group_id; /**< Group ID of owner, -1 if unknown. */
int64_t filemode; /**< Unix file mode, -1 if unknown. */
} AVIODirEntry;

typedef struct AVIODirContext {
struct URLContext *url_context;
} AVIODirContext;

/**
* Bytestream IO Context.
* New fields can be added to the end with minor version bumps.
Expand Down Expand Up @@ -180,6 +220,48 @@ 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 A dictionary filled with protocol-private options. On return
* this parameter will be destroyed and replaced with a dictionary
* containing options that were not found. May be NULL.
* @return >=0 on success or negative on error.
*/
int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options);

/**
* Get next directory entry.
*
* Returned entry must be freed with avio_free_directory_entry(). In particular
* it may outlive AVIODirContext.
*
* @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(AVIODirContext *s, AVIODirEntry **next);

/**
* Close directory.
*
* @note Entries created using avio_read_dir() are not deleted and must be
* freeded with avio_free_directory_entry().
*
* @param s directory read context.
* @return >=0 on success or negative on error.
*/
int avio_close_dir(AVIODirContext **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().
Expand Down
16 changes: 16 additions & 0 deletions libavformat/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,19 @@ void ff_make_absolute_url(char *buf, int size, const char *base,
}
av_strlcat(buf, rel, size);
}

AVIODirEntry *ff_alloc_dir_entry(void)
{
AVIODirEntry *entry = av_mallocz(sizeof(AVIODirEntry));
if (entry) {
entry->type = AVIO_ENTRY_UNKNOWN;
entry->size = -1;
entry->modification_timestamp = -1;
entry->access_timestamp = -1;
entry->status_change_timestamp = -1;
entry->user_id = -1;
entry->group_id = -1;
entry->filemode = -1;
}
return entry;
}
10 changes: 10 additions & 0 deletions libavformat/url.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -280,5 +283,12 @@ 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);

/**
* Allocate directory entry with default values.
*
* @return entry or NULL on error
*/
AVIODirEntry *ff_alloc_dir_entry(void);


#endif /* AVFORMAT_URL_H */

0 comments on commit 184084c

Please sign in to comment.