mirror of
https://github.com/mpv-player/mpv
synced 2024-12-24 15:52:25 +00:00
core: update metadata during playback, allow streams to export metadata
STREAM_CTRL_GET_METADATA will be used to poll for streamcast metadata. Also add DEMUXER_CTRL_UPDATE_INFO, which could in theory be used by demux_lavf.c. (Unfortunately, libavformat is too crappy to read metadata mid-stream for mp3 or ogg, so we don't implement it.)
This commit is contained in:
parent
e00621ac46
commit
3f3ffd0de4
@ -226,6 +226,7 @@ typedef struct MPContext {
|
|||||||
double audio_delay;
|
double audio_delay;
|
||||||
|
|
||||||
double last_heartbeat;
|
double last_heartbeat;
|
||||||
|
double last_metadata_update;
|
||||||
|
|
||||||
double mouse_timer;
|
double mouse_timer;
|
||||||
unsigned int mouse_event_ts;
|
unsigned int mouse_event_ts;
|
||||||
|
@ -3643,6 +3643,11 @@ static void run_playloop(struct MPContext *mpctx)
|
|||||||
mp_input_get_cmd(mpctx->input, sleeptime * 1000, true);
|
mp_input_get_cmd(mpctx->input, sleeptime * 1000, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mp_time_sec() > mpctx->last_metadata_update + 2) {
|
||||||
|
demux_info_update(mpctx->demuxer);
|
||||||
|
mpctx->last_metadata_update = mp_time_sec();
|
||||||
|
}
|
||||||
|
|
||||||
//================= Keyboard events, SEEKing ====================
|
//================= Keyboard events, SEEKing ====================
|
||||||
|
|
||||||
handle_pause_on_low_cache(mpctx);
|
handle_pause_on_low_cache(mpctx);
|
||||||
|
@ -976,6 +976,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts,
|
|||||||
}
|
}
|
||||||
add_stream_chapters(demuxer);
|
add_stream_chapters(demuxer);
|
||||||
demuxer_sort_chapters(demuxer);
|
demuxer_sort_chapters(demuxer);
|
||||||
|
demux_info_update(demuxer);
|
||||||
return demuxer;
|
return demuxer;
|
||||||
} else {
|
} else {
|
||||||
// demux_mov can return playlist instead of mov
|
// demux_mov can return playlist instead of mov
|
||||||
@ -1227,6 +1228,18 @@ char *demux_info_get(demuxer_t *demuxer, const char *opt)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void demux_info_update(struct demuxer *demuxer)
|
||||||
|
{
|
||||||
|
demux_control(demuxer, DEMUXER_CTRL_UPDATE_INFO, NULL);
|
||||||
|
// Take care of stream metadata as well
|
||||||
|
char **meta;
|
||||||
|
if (stream_control(demuxer->stream, STREAM_CTRL_GET_METADATA, &meta) > 0) {
|
||||||
|
for (int n = 0; meta[n + 0]; n += 2)
|
||||||
|
demux_info_add(demuxer, meta[n + 0], meta[n + 1]);
|
||||||
|
talloc_free(meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int demux_control(demuxer_t *demuxer, int cmd, void *arg)
|
int demux_control(demuxer_t *demuxer, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ enum timestamp_type {
|
|||||||
#define DEMUXER_CTRL_OK 1
|
#define DEMUXER_CTRL_OK 1
|
||||||
#define DEMUXER_CTRL_GUESS 2
|
#define DEMUXER_CTRL_GUESS 2
|
||||||
|
|
||||||
|
#define DEMUXER_CTRL_UPDATE_INFO 8
|
||||||
#define DEMUXER_CTRL_SWITCHED_TRACKS 9
|
#define DEMUXER_CTRL_SWITCHED_TRACKS 9
|
||||||
#define DEMUXER_CTRL_GET_TIME_LENGTH 10
|
#define DEMUXER_CTRL_GET_TIME_LENGTH 10
|
||||||
#define DEMUXER_CTRL_GET_START_TIME 11
|
#define DEMUXER_CTRL_GET_START_TIME 11
|
||||||
@ -385,6 +386,8 @@ int demux_info_add_bstr(struct demuxer *demuxer, struct bstr opt,
|
|||||||
struct bstr param);
|
struct bstr param);
|
||||||
char *demux_info_get(struct demuxer *demuxer, const char *opt);
|
char *demux_info_get(struct demuxer *demuxer, const char *opt);
|
||||||
int demux_info_print(struct demuxer *demuxer);
|
int demux_info_print(struct demuxer *demuxer);
|
||||||
|
void demux_info_update(struct demuxer *demuxer);
|
||||||
|
|
||||||
int demux_control(struct demuxer *demuxer, int cmd, void *arg);
|
int demux_control(struct demuxer *demuxer, int cmd, void *arg);
|
||||||
|
|
||||||
void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
|
void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
// Time in seconds the cache updates "cached" controls. Note that idle mode
|
// Time in seconds the cache updates "cached" controls. Note that idle mode
|
||||||
// will block the cache from doing this, and this timeout is honored only if
|
// will block the cache from doing this, and this timeout is honored only if
|
||||||
// the cache is active.
|
// the cache is active.
|
||||||
#define CACHE_UPDATE_CONTROLS_TIME 0.1
|
#define CACHE_UPDATE_CONTROLS_TIME 2.0
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -102,6 +102,7 @@ struct priv {
|
|||||||
unsigned int stream_num_chapters;
|
unsigned int stream_num_chapters;
|
||||||
int stream_cache_idle;
|
int stream_cache_idle;
|
||||||
int stream_cache_fill;
|
int stream_cache_fill;
|
||||||
|
char **stream_metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store additional per-byte metadata. Since per-byte would be way too
|
// Store additional per-byte metadata. Since per-byte would be way too
|
||||||
@ -306,6 +307,7 @@ static void update_cached_controls(struct priv *s)
|
|||||||
{
|
{
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
double d;
|
double d;
|
||||||
|
char **m;
|
||||||
s->stream_time_length = 0;
|
s->stream_time_length = 0;
|
||||||
if (stream_control(s->stream, STREAM_CTRL_GET_TIME_LENGTH, &d) == STREAM_OK)
|
if (stream_control(s->stream, STREAM_CTRL_GET_TIME_LENGTH, &d) == STREAM_OK)
|
||||||
s->stream_time_length = d;
|
s->stream_time_length = d;
|
||||||
@ -318,6 +320,10 @@ static void update_cached_controls(struct priv *s)
|
|||||||
s->stream_num_chapters = 0;
|
s->stream_num_chapters = 0;
|
||||||
if (stream_control(s->stream, STREAM_CTRL_GET_NUM_CHAPTERS, &ui) == STREAM_OK)
|
if (stream_control(s->stream, STREAM_CTRL_GET_NUM_CHAPTERS, &ui) == STREAM_OK)
|
||||||
s->stream_num_chapters = ui;
|
s->stream_num_chapters = ui;
|
||||||
|
if (stream_control(s->stream, STREAM_CTRL_GET_METADATA, &m) == STREAM_OK) {
|
||||||
|
talloc_free(s->stream_metadata);
|
||||||
|
s->stream_metadata = talloc_steal(s, m);
|
||||||
|
}
|
||||||
stream_update_size(s->stream);
|
stream_update_size(s->stream);
|
||||||
s->stream_size = s->stream->end_pos;
|
s->stream_size = s->stream->end_pos;
|
||||||
}
|
}
|
||||||
@ -368,6 +374,21 @@ static int cache_get_cached_control(stream_t *cache, int cmd, void *arg)
|
|||||||
}
|
}
|
||||||
return STREAM_UNSUPPORTED;
|
return STREAM_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
case STREAM_CTRL_GET_METADATA: {
|
||||||
|
if (s->stream_metadata && s->stream_metadata[0]) {
|
||||||
|
char **m = talloc_new(NULL);
|
||||||
|
int num_m = 0;
|
||||||
|
for (int n = 0; s->stream_metadata[n]; n++) {
|
||||||
|
char *t = talloc_strdup(m, s->stream_metadata[n]);
|
||||||
|
MP_TARRAY_APPEND(NULL, m, num_m, t);
|
||||||
|
}
|
||||||
|
MP_TARRAY_APPEND(NULL, m, num_m, NULL);
|
||||||
|
MP_TARRAY_APPEND(NULL, m, num_m, NULL);
|
||||||
|
*(char ***)arg = m;
|
||||||
|
return STREAM_OK;
|
||||||
|
}
|
||||||
|
return STREAM_UNSUPPORTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return STREAM_ERROR;
|
return STREAM_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
#define STREAM_CTRL_GET_CHAPTER_TIME 21
|
#define STREAM_CTRL_GET_CHAPTER_TIME 21
|
||||||
#define STREAM_CTRL_GET_DVD_INFO 22
|
#define STREAM_CTRL_GET_DVD_INFO 22
|
||||||
#define STREAM_CTRL_SET_CONTENTS 23
|
#define STREAM_CTRL_SET_CONTENTS 23
|
||||||
|
#define STREAM_CTRL_GET_METADATA 24
|
||||||
|
|
||||||
struct stream_lang_req {
|
struct stream_lang_req {
|
||||||
int type; // STREAM_AUDIO, STREAM_SUB
|
int type; // STREAM_AUDIO, STREAM_SUB
|
||||||
|
Loading…
Reference in New Issue
Block a user