mirror of
https://github.com/mpv-player/mpv
synced 2024-12-27 01:22:30 +00:00
af_lavfi: implement af-metadata property
Works like vf-metadata. Unfortunately requires some code duplication (even though it's not much). Fixes #2311.
This commit is contained in:
parent
f095e86b61
commit
4e0e24c3c2
@ -19,6 +19,8 @@ Interface changes
|
||||
|
||||
::
|
||||
|
||||
--- mpv 0.11.0 ---
|
||||
- add "af-metadata" property
|
||||
--- mpv 0.10.0 ---
|
||||
- add --video-aspect-method option
|
||||
- add --playlist-pos option
|
||||
|
@ -1091,6 +1091,9 @@ Property list
|
||||
An example of these kind of metadata are the cropping parameters
|
||||
added by ``--vf=lavfi=cropdetect``.
|
||||
|
||||
``af-metadata/<filter-label>``
|
||||
Equivalent to ``vf-metadata/<filter-label>``, but for audio filters.
|
||||
|
||||
``pause`` (RW)
|
||||
Pause status. This is usually ``yes`` or ``no``. See ``--pause``.
|
||||
|
||||
|
@ -695,6 +695,18 @@ void af_control_all(struct af_stream *s, int cmd, void *arg)
|
||||
af->control(af, cmd, arg);
|
||||
}
|
||||
|
||||
int af_control_by_label(struct af_stream *s, int cmd, void *arg, bstr label)
|
||||
{
|
||||
char *label_str = bstrdup0(NULL, label);
|
||||
struct af_instance *cur = af_find_by_label(s, label_str);
|
||||
talloc_free(label_str);
|
||||
if (cur) {
|
||||
return cur->control ? cur->control(cur, cmd, arg) : CONTROL_NA;
|
||||
} else {
|
||||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Used by filters to add a filtered frame to the output queue.
|
||||
// Ownership of frame is transferred from caller to the filter chain.
|
||||
void af_add_output_frame(struct af_instance *af, struct mp_audio *frame)
|
||||
|
@ -127,6 +127,7 @@ enum af_control {
|
||||
AF_CONTROL_GET_PAN_BALANCE,
|
||||
AF_CONTROL_SET_PLAYBACK_SPEED,
|
||||
AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE,
|
||||
AF_CONTROL_GET_METADATA,
|
||||
};
|
||||
|
||||
// Argument for AF_CONTROL_SET_PAN_LEVEL
|
||||
@ -145,6 +146,7 @@ int af_remove_by_label(struct af_stream *s, char *label);
|
||||
struct af_instance *af_find_by_label(struct af_stream *s, char *label);
|
||||
struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg);
|
||||
void af_control_all(struct af_stream *s, int cmd, void *arg);
|
||||
int af_control_by_label(struct af_stream *s, int cmd, void *arg, bstr label);
|
||||
void af_seek_reset(struct af_stream *s);
|
||||
|
||||
void af_add_output_frame(struct af_instance *af, struct mp_audio *frame);
|
||||
|
@ -34,11 +34,14 @@
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "audio/format.h"
|
||||
#include "audio/fmt-conversion.h"
|
||||
#include "af.h"
|
||||
|
||||
#include "common/av_common.h"
|
||||
#include "common/tags.h"
|
||||
|
||||
#include "options/m_option.h"
|
||||
|
||||
@ -63,6 +66,8 @@ struct priv {
|
||||
|
||||
bool eof;
|
||||
|
||||
struct mp_tags *metadata;
|
||||
|
||||
// options
|
||||
char *cfg_graph;
|
||||
char **cfg_avopts;
|
||||
@ -213,6 +218,12 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
||||
|
||||
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
|
||||
}
|
||||
case AF_CONTROL_GET_METADATA:
|
||||
if (p->metadata) {
|
||||
*(struct mp_tags *)arg = *p->metadata;
|
||||
return CONTROL_OK;
|
||||
}
|
||||
return CONTROL_NA;
|
||||
case AF_CONTROL_RESET:
|
||||
reset(af);
|
||||
return AF_OK;
|
||||
@ -220,6 +231,17 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
||||
return AF_UNKNOWN;
|
||||
}
|
||||
|
||||
static void get_metadata_from_av_frame(struct af_instance *af, AVFrame *frame)
|
||||
{
|
||||
#if HAVE_AVFRAME_METADATA
|
||||
struct priv *p = af->priv;
|
||||
if (!p->metadata)
|
||||
p->metadata = talloc_zero(p, struct mp_tags);
|
||||
|
||||
mp_tags_copy_from_av_dictionary(p->metadata, av_frame_get_metadata(frame));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int filter_frame(struct af_instance *af, struct mp_audio *data)
|
||||
{
|
||||
struct priv *p = af->priv;
|
||||
@ -307,6 +329,7 @@ static int filter_out(struct af_instance *af)
|
||||
af->delay = in_time - out_time;
|
||||
}
|
||||
|
||||
get_metadata_from_av_frame(af, frame);
|
||||
af_add_output_frame(af, out);
|
||||
av_frame_free(&frame);
|
||||
return 0;
|
||||
|
@ -1187,21 +1187,31 @@ static int mp_property_chapter_metadata(void *ctx, struct m_property *prop,
|
||||
return tag_property(action, arg, mpctx->chapters[chapter].metadata);
|
||||
}
|
||||
|
||||
static int mp_property_vf_metadata(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
static int mp_property_filter_metadata(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
if (!(mpctx->d_video && mpctx->d_video->vfilter))
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
struct vf_chain *vf = mpctx->d_video->vfilter;
|
||||
const char *type = prop->priv;
|
||||
|
||||
if (action == M_PROPERTY_KEY_ACTION) {
|
||||
struct m_property_action_arg *ka = arg;
|
||||
bstr key;
|
||||
char *rem;
|
||||
m_property_split_path(ka->key, &key, &rem);
|
||||
struct mp_tags vf_metadata = {0};
|
||||
switch (vf_control_by_label(vf, VFCTRL_GET_METADATA, &vf_metadata, key)) {
|
||||
struct mp_tags metadata = {0};
|
||||
int res = CONTROL_UNKNOWN;
|
||||
if (strcmp(type, "vf") == 0) {
|
||||
if (!(mpctx->d_video && mpctx->d_video->vfilter))
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
struct vf_chain *vf = mpctx->d_video->vfilter;
|
||||
res = vf_control_by_label(vf, VFCTRL_GET_METADATA, &metadata, key);
|
||||
} else if (strcmp(type, "af") == 0) {
|
||||
if (!(mpctx->d_audio && mpctx->d_audio->afilter))
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
struct af_stream *af = mpctx->d_audio->afilter;
|
||||
res = af_control_by_label(af, AF_CONTROL_GET_METADATA, &metadata, key);
|
||||
}
|
||||
switch (res) {
|
||||
case CONTROL_UNKNOWN:
|
||||
return M_PROPERTY_UNKNOWN;
|
||||
case CONTROL_NA: // empty
|
||||
@ -1209,9 +1219,9 @@ static int mp_property_vf_metadata(void *ctx, struct m_property *prop,
|
||||
if (strlen(rem)) {
|
||||
struct m_property_action_arg next_ka = *ka;
|
||||
next_ka.key = rem;
|
||||
return tag_property(M_PROPERTY_KEY_ACTION, &next_ka, &vf_metadata);
|
||||
return tag_property(M_PROPERTY_KEY_ACTION, &next_ka, &metadata);
|
||||
} else {
|
||||
return tag_property(ka->action, ka->arg, &vf_metadata);
|
||||
return tag_property(ka->action, ka->arg, &metadata);
|
||||
}
|
||||
return M_PROPERTY_OK;
|
||||
default:
|
||||
@ -3379,7 +3389,8 @@ static const struct m_property mp_properties[] = {
|
||||
{"metadata", mp_property_metadata},
|
||||
{"filtered-metadata", mp_property_filtered_metadata},
|
||||
{"chapter-metadata", mp_property_chapter_metadata},
|
||||
{"vf-metadata", mp_property_vf_metadata},
|
||||
{"vf-metadata", mp_property_filter_metadata, .priv = "vf"},
|
||||
{"af-metadata", mp_property_filter_metadata, .priv = "af"},
|
||||
{"pause", mp_property_pause},
|
||||
{"core-idle", mp_property_core_idle},
|
||||
{"eof-reached", mp_property_eof_reached},
|
||||
|
Loading…
Reference in New Issue
Block a user