demux: refactor tag handling

Make the code somewhat reuseable, instead of bound to a single demuxer
instance. The plan is to add support for per-chapter tags later.
This commit is contained in:
wm4 2013-09-08 06:32:48 +02:00
parent 1aae5981a7
commit ba07000b88
3 changed files with 86 additions and 50 deletions

View File

@ -542,6 +542,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts,
.filepos = -1,
.opts = opts,
.filename = talloc_strdup(demuxer, stream->url),
.metadata = talloc_zero(demuxer, struct mp_tags),
};
demuxer->params = params; // temporary during open()
stream_seek(stream, stream->start_pos);
@ -684,6 +685,42 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, int flags)
return 1;
}
void mp_tags_set_str(struct mp_tags *tags, const char *key, const char *value)
{
mp_tags_set_bstr(tags, bstr0(key), bstr0(value));
}
void mp_tags_set_bstr(struct mp_tags *tags, bstr key, bstr value)
{
for (int n = 0; n < tags->num_keys; n++) {
if (bstrcasecmp0(key, tags->keys[n]) == 0) {
talloc_free(tags->values[n]);
tags->values[n] = talloc_strndup(tags, value.start, value.len);
return;
}
}
MP_RESIZE_ARRAY(tags, tags->keys, tags->num_keys + 1);
MP_RESIZE_ARRAY(tags, tags->values, tags->num_keys + 1);
tags->keys[tags->num_keys] = talloc_strndup(tags, key.start, key.len);
tags->values[tags->num_keys] = talloc_strndup(tags, value.start, value.len);
tags->num_keys++;
}
char *mp_tags_get_str(struct mp_tags *tags, const char *key)
{
return mp_tags_get_bstr(tags, bstr0(key));
}
char *mp_tags_get_bstr(struct mp_tags *tags, bstr key)
{
for (int n = 0; n < tags->num_keys; n++) {
if (bstrcasecmp0(key, tags->keys[n]) == 0)
return tags->values[n];
}
return NULL;
}
int demux_info_add(demuxer_t *demuxer, const char *opt, const char *param)
{
return demux_info_add_bstr(demuxer, bstr0(opt), bstr0(param));
@ -691,49 +728,34 @@ int demux_info_add(demuxer_t *demuxer, const char *opt, const char *param)
int demux_info_add_bstr(demuxer_t *demuxer, struct bstr opt, struct bstr param)
{
char **info = demuxer->info;
int n = 0;
for (n = 0; info && info[2 * n] != NULL; n++) {
if (!bstrcasecmp(opt, bstr0(info[2*n]))) {
if (!bstrcmp(param, bstr0(info[2*n + 1]))) {
mp_msg(MSGT_DEMUX, MSGL_V, "Demuxer info %.*s set to unchanged value %.*s\n",
BSTR_P(opt), BSTR_P(param));
return 0;
}
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "Demuxer info %.*s changed to %.*s\n",
BSTR_P(opt), BSTR_P(param));
talloc_free(info[2*n + 1]);
info[2*n + 1] = talloc_strndup(demuxer->info, param.start, param.len);
char *oldval = mp_tags_get_bstr(demuxer->metadata, opt);
if (oldval) {
if (bstrcmp0(param, oldval) == 0)
return 0;
}
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "Demuxer info %.*s changed to %.*s\n",
BSTR_P(opt), BSTR_P(param));
}
info = demuxer->info = talloc_realloc(demuxer, info, char *, 2 * (n + 2));
info[2*n] = talloc_strndup(demuxer->info, opt.start, opt.len);
info[2*n + 1] = talloc_strndup(demuxer->info, param.start, param.len);
memset(&info[2 * (n + 1)], 0, 2 * sizeof(char *));
mp_tags_set_bstr(demuxer->metadata, opt, param);
return 1;
}
int demux_info_print(demuxer_t *demuxer)
{
char **info = demuxer->info;
struct mp_tags *info = demuxer->metadata;
int n;
if (!info)
return 0;
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "Clip info:\n");
for (n = 0; info[2 * n] != NULL; n++) {
mp_msg(MSGT_DEMUX, MSGL_INFO, " %s: %s\n", info[2 * n],
info[2 * n + 1]);
for (n = 0; n < info->num_keys; n++) {
mp_msg(MSGT_DEMUX, MSGL_INFO, " %s: %s\n", info->keys[n],
info->values[n]);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CLIP_INFO_NAME%d=%s\n", n,
info[2 * n]);
info->keys[n]);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CLIP_INFO_VALUE%d=%s\n", n,
info[2 * n + 1]);
info->values[n]);
}
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CLIP_INFO_N=%d\n", n);
@ -742,15 +764,7 @@ int demux_info_print(demuxer_t *demuxer)
char *demux_info_get(demuxer_t *demuxer, const char *opt)
{
int i;
char **info = demuxer->info;
for (i = 0; info && info[2 * i] != NULL; i++) {
if (!strcasecmp(opt, info[2 * i]))
return info[2 * i + 1];
}
return NULL;
return mp_tags_get_str(demuxer->metadata, opt);
}
void demux_info_update(struct demuxer *demuxer)

View File

@ -111,6 +111,12 @@ typedef struct demuxer_desc {
int (*control)(struct demuxer *demuxer, int cmd, void *arg);
} demuxer_desc_t;
struct mp_tags {
char **keys;
char **values;
int num_keys;
};
typedef struct demux_chapter
{
int original_index;
@ -185,8 +191,9 @@ typedef struct demuxer {
// If the file is a playlist file
struct playlist *playlist;
struct mp_tags *metadata;
void *priv; // demuxer-specific internal data
char **info; // metadata
struct MPOpts *opts;
struct demuxer_params *params;
} demuxer_t;
@ -282,4 +289,9 @@ double demux_packet_list_duration(struct demux_packet **pkts, int num_pkts);
struct demux_packet *demux_packet_list_fill(struct demux_packet **pkts,
int num_pkts, int *current);
void mp_tags_set_str(struct mp_tags *tags, const char *key, const char *value);
void mp_tags_set_bstr(struct mp_tags *tags, bstr key, bstr value);
char *mp_tags_get_str(struct mp_tags *tags, const char *key);
char *mp_tags_get_bstr(struct mp_tags *tags, bstr key);
#endif /* MPLAYER_DEMUXER_H */

View File

@ -636,39 +636,38 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg,
return M_PROPERTY_NOT_IMPLEMENTED;
}
/// Demuxer meta data
static int mp_property_metadata(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
static int tag_property(m_option_t *prop, int action, void *arg,
struct mp_tags *tags)
{
struct demuxer *demuxer = mpctx->master_demuxer;
if (!demuxer)
return M_PROPERTY_UNAVAILABLE;
static const m_option_t key_type =
{
"metadata", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL
"tags", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL
};
switch (action) {
case M_PROPERTY_GET: {
char **slist = NULL;
m_option_copy(prop, &slist, &demuxer->info);
int num = 0;
for (int n = 0; n < tags->num_keys; n++) {
MP_TARRAY_APPEND(NULL, slist, num, tags->keys[n]);
MP_TARRAY_APPEND(NULL, slist, num, tags->values[n]);
}
MP_TARRAY_APPEND(NULL, slist, num, NULL);
*(char ***)arg = slist;
return M_PROPERTY_OK;
}
case M_PROPERTY_PRINT: {
char **list = demuxer->info;
char *res = NULL;
for (int n = 0; list && list[n]; n += 2) {
for (int n = 0; n < tags->num_keys; n++) {
res = talloc_asprintf_append_buffer(res, "%s: %s\n",
list[n], list[n + 1]);
tags->keys[n], tags->values[n]);
}
*(char **)arg = res;
return res ? M_PROPERTY_OK : M_PROPERTY_UNAVAILABLE;
}
case M_PROPERTY_KEY_ACTION: {
struct m_property_action_arg *ka = arg;
char *meta = demux_info_get(demuxer, ka->key);
char *meta = mp_tags_get_str(tags, ka->key);
if (!meta)
return M_PROPERTY_UNKNOWN;
switch (ka->action) {
@ -684,6 +683,17 @@ static int mp_property_metadata(m_option_t *prop, int action, void *arg,
return M_PROPERTY_NOT_IMPLEMENTED;
}
/// Demuxer meta data
static int mp_property_metadata(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
struct demuxer *demuxer = mpctx->master_demuxer;
if (!demuxer)
return M_PROPERTY_UNAVAILABLE;
return tag_property(prop, action, arg, demuxer->metadata);
}
static int mp_property_pause(m_option_t *prop, int action, void *arg,
void *ctx)
{