Merge pull request #2365 from cg2121/media-stuff

obs-ffmpeg, vlc-video: Add media control support
master
Jim 2020-02-05 11:52:02 -08:00 committed by GitHub
commit 0c4bdde153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 252 additions and 16 deletions

View File

@ -40,9 +40,12 @@ ColorRange="YUV Color Range"
ColorRange.Auto="Auto" ColorRange.Auto="Auto"
ColorRange.Partial="Partial" ColorRange.Partial="Partial"
ColorRange.Full="Full" ColorRange.Full="Full"
RestartMedia="Restart Media" RestartMedia="Restart"
SpeedPercentage="Speed" SpeedPercentage="Speed"
Seekable="Seekable" Seekable="Seekable"
Play="Play"
Pause="Pause"
Stop="Stop"
MediaFileFilter.AllMediaFiles="All Media Files" MediaFileFilter.AllMediaFiles="All Media Files"
MediaFileFilter.VideoFiles="Video Files" MediaFileFilter.VideoFiles="Video Files"

View File

@ -57,8 +57,18 @@ struct ffmpeg_source {
bool restart_on_activate; bool restart_on_activate;
bool close_when_inactive; bool close_when_inactive;
bool seekable; bool seekable;
enum obs_media_state state;
obs_hotkey_pair_id play_pause_hotkey;
obs_hotkey_id stop_hotkey;
}; };
static void set_media_state(void *data, enum obs_media_state state)
{
struct ffmpeg_source *s = data;
s->state = state;
}
static bool is_local_file_modified(obs_properties_t *props, static bool is_local_file_modified(obs_properties_t *props,
obs_property_t *prop, obs_data_t *settings) obs_property_t *prop, obs_data_t *settings)
{ {
@ -297,6 +307,7 @@ static void ffmpeg_source_start(struct ffmpeg_source *s)
mp_media_play(&s->media, s->is_looping); mp_media_play(&s->media, s->is_looping);
if (s->is_local_file) if (s->is_local_file)
obs_source_show_preloaded_video(s->source); obs_source_show_preloaded_video(s->source);
set_media_state(s, OBS_MEDIA_STATE_PLAYING);
} }
} }
@ -374,7 +385,7 @@ static void restart_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
struct ffmpeg_source *s = data; struct ffmpeg_source *s = data;
if (obs_source_active(s->source)) if (obs_source_active(s->source))
ffmpeg_source_start(s); obs_source_media_restart(s->source);
} }
static void restart_proc(void *data, calldata_t *cd) static void restart_proc(void *data, calldata_t *cd)
@ -430,6 +441,50 @@ static void get_nb_frames(void *data, calldata_t *cd)
calldata_set_int(cd, "num_frames", frames); calldata_set_int(cd, "num_frames", frames);
} }
static bool ffmpeg_source_play_hotkey(void *data, obs_hotkey_pair_id id,
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
struct ffmpeg_source *s = data;
if (s->state == OBS_MEDIA_STATE_PLAYING || !pressed ||
!obs_source_active(s->source))
return false;
obs_source_media_play_pause(s->source, false);
return true;
}
static bool ffmpeg_source_pause_hotkey(void *data, obs_hotkey_pair_id id,
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
struct ffmpeg_source *s = data;
if (s->state != OBS_MEDIA_STATE_PLAYING || !pressed ||
!obs_source_active(s->source))
return false;
obs_source_media_play_pause(s->source, true);
return true;
}
static void ffmpeg_source_stop_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
struct ffmpeg_source *s = data;
if (pressed && obs_source_active(s->source))
obs_source_media_stop(s->source);
}
static void *ffmpeg_source_create(obs_data_t *settings, obs_source_t *source) static void *ffmpeg_source_create(obs_data_t *settings, obs_source_t *source)
{ {
UNUSED_PARAMETER(settings); UNUSED_PARAMETER(settings);
@ -441,6 +496,16 @@ static void *ffmpeg_source_create(obs_data_t *settings, obs_source_t *source)
obs_module_text("RestartMedia"), obs_module_text("RestartMedia"),
restart_hotkey, s); restart_hotkey, s);
s->play_pause_hotkey = obs_hotkey_pair_register_source(
s->source, "MediaSource.Play", obs_module_text("Play"),
"MediaSource.Pause", obs_module_text("Pause"),
ffmpeg_source_play_hotkey, ffmpeg_source_pause_hotkey, s, s);
s->stop_hotkey = obs_hotkey_register_source(source, "MediaSource.Stop",
obs_module_text("Stop"),
ffmpeg_source_stop_hotkey,
s);
proc_handler_t *ph = obs_source_get_proc_handler(source); proc_handler_t *ph = obs_source_get_proc_handler(source);
proc_handler_add(ph, "void restart()", restart_proc, s); proc_handler_add(ph, "void restart()", restart_proc, s);
proc_handler_add(ph, "void get_duration(out int duration)", proc_handler_add(ph, "void get_duration(out int duration)",
@ -474,7 +539,7 @@ static void ffmpeg_source_activate(void *data)
struct ffmpeg_source *s = data; struct ffmpeg_source *s = data;
if (s->restart_on_activate) if (s->restart_on_activate)
ffmpeg_source_start(s); obs_source_media_restart(s->source);
} }
static void ffmpeg_source_deactivate(void *data) static void ffmpeg_source_deactivate(void *data)
@ -491,11 +556,77 @@ static void ffmpeg_source_deactivate(void *data)
} }
} }
static void ffmpeg_source_play_pause(void *data, bool pause)
{
struct ffmpeg_source *s = data;
mp_media_play_pause(&s->media, pause);
if (pause)
set_media_state(s, OBS_MEDIA_STATE_PAUSED);
else
set_media_state(s, OBS_MEDIA_STATE_PLAYING);
}
static void ffmpeg_source_stop(void *data)
{
struct ffmpeg_source *s = data;
if (s->media_valid) {
mp_media_stop(&s->media);
obs_source_output_video(s->source, NULL);
set_media_state(s, OBS_MEDIA_STATE_STOPPED);
}
}
static void ffmpeg_source_restart(void *data)
{
struct ffmpeg_source *s = data;
if (obs_source_active(s->source))
ffmpeg_source_start(s);
set_media_state(s, OBS_MEDIA_STATE_PLAYING);
}
static int64_t ffmpeg_source_get_duration(void *data)
{
struct ffmpeg_source *s = data;
int64_t dur = 0;
if (s->media.fmt)
dur = (float)s->media.fmt->duration / 1000.0f;
return dur;
}
static int64_t ffmpeg_source_get_time(void *data)
{
struct ffmpeg_source *s = data;
return mp_get_current_time(&s->media);
}
static void ffmpeg_source_set_time(void *data, int64_t ms)
{
struct ffmpeg_source *s = data;
mp_media_seek_to(&s->media, ms);
}
static enum obs_media_state ffmpeg_source_get_state(void *data)
{
struct ffmpeg_source *s = data;
return s->state;
}
struct obs_source_info ffmpeg_source = { struct obs_source_info ffmpeg_source = {
.id = "ffmpeg_source", .id = "ffmpeg_source",
.type = OBS_SOURCE_TYPE_INPUT, .type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | .output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO |
OBS_SOURCE_DO_NOT_DUPLICATE, OBS_SOURCE_DO_NOT_DUPLICATE |
OBS_SOURCE_CONTROLLABLE_MEDIA,
.get_name = ffmpeg_source_getname, .get_name = ffmpeg_source_getname,
.create = ffmpeg_source_create, .create = ffmpeg_source_create,
.destroy = ffmpeg_source_destroy, .destroy = ffmpeg_source_destroy,
@ -506,4 +637,11 @@ struct obs_source_info ffmpeg_source = {
.video_tick = ffmpeg_source_tick, .video_tick = ffmpeg_source_tick,
.update = ffmpeg_source_update, .update = ffmpeg_source_update,
.icon_type = OBS_ICON_TYPE_MEDIA, .icon_type = OBS_ICON_TYPE_MEDIA,
.media_play_pause = ffmpeg_source_play_pause,
.media_restart = ffmpeg_source_restart,
.media_stop = ffmpeg_source_stop,
.media_get_duration = ffmpeg_source_get_duration,
.media_get_time = ffmpeg_source_get_time,
.media_set_time = ffmpeg_source_set_time,
.media_get_state = ffmpeg_source_get_state,
}; };

View File

@ -36,8 +36,11 @@ LIBVLC_AUDIO_SET_FORMAT_CALLBACKS libvlc_audio_set_format_callbacks_;
LIBVLC_MEDIA_PLAYER_PLAY libvlc_media_player_play_; LIBVLC_MEDIA_PLAYER_PLAY libvlc_media_player_play_;
LIBVLC_MEDIA_PLAYER_STOP libvlc_media_player_stop_; LIBVLC_MEDIA_PLAYER_STOP libvlc_media_player_stop_;
LIBVLC_MEDIA_PLAYER_GET_TIME libvlc_media_player_get_time_; LIBVLC_MEDIA_PLAYER_GET_TIME libvlc_media_player_get_time_;
LIBVLC_MEDIA_PLAYER_SET_TIME libvlc_media_player_set_time_;
LIBVLC_VIDEO_GET_SIZE libvlc_video_get_size_; LIBVLC_VIDEO_GET_SIZE libvlc_video_get_size_;
LIBVLC_MEDIA_PLAYER_EVENT_MANAGER libvlc_media_player_event_manager_; LIBVLC_MEDIA_PLAYER_EVENT_MANAGER libvlc_media_player_event_manager_;
LIBVLC_MEDIA_PLAYER_GET_STATE libvlc_media_player_get_state_;
LIBVLC_MEDIA_PLAYER_GET_LENGTH libvlc_media_player_get_length_;
/* libvlc media list */ /* libvlc media list */
LIBVLC_MEDIA_LIST_NEW libvlc_media_list_new_; LIBVLC_MEDIA_LIST_NEW libvlc_media_list_new_;
@ -108,8 +111,11 @@ static bool load_vlc_funcs(void)
LOAD_VLC_FUNC(libvlc_media_player_play); LOAD_VLC_FUNC(libvlc_media_player_play);
LOAD_VLC_FUNC(libvlc_media_player_stop); LOAD_VLC_FUNC(libvlc_media_player_stop);
LOAD_VLC_FUNC(libvlc_media_player_get_time); LOAD_VLC_FUNC(libvlc_media_player_get_time);
LOAD_VLC_FUNC(libvlc_media_player_set_time);
LOAD_VLC_FUNC(libvlc_video_get_size); LOAD_VLC_FUNC(libvlc_video_get_size);
LOAD_VLC_FUNC(libvlc_media_player_event_manager); LOAD_VLC_FUNC(libvlc_media_player_event_manager);
LOAD_VLC_FUNC(libvlc_media_player_get_state);
LOAD_VLC_FUNC(libvlc_media_player_get_length);
/* libvlc media list */ /* libvlc media list */
LOAD_VLC_FUNC(libvlc_media_list_new); LOAD_VLC_FUNC(libvlc_media_list_new);

View File

@ -61,10 +61,16 @@ typedef int (*LIBVLC_MEDIA_PLAYER_PLAY)(libvlc_media_player_t *p_mi);
typedef void (*LIBVLC_MEDIA_PLAYER_STOP)(libvlc_media_player_t *p_mi); typedef void (*LIBVLC_MEDIA_PLAYER_STOP)(libvlc_media_player_t *p_mi);
typedef libvlc_time_t (*LIBVLC_MEDIA_PLAYER_GET_TIME)( typedef libvlc_time_t (*LIBVLC_MEDIA_PLAYER_GET_TIME)(
libvlc_media_player_t *p_mi); libvlc_media_player_t *p_mi);
typedef void (*LIBVLC_MEDIA_PLAYER_SET_TIME)(libvlc_media_player_t *p_mi,
libvlc_time_t i_time);
typedef int (*LIBVLC_VIDEO_GET_SIZE)(libvlc_media_player_t *p_mi, unsigned num, typedef int (*LIBVLC_VIDEO_GET_SIZE)(libvlc_media_player_t *p_mi, unsigned num,
unsigned *px, unsigned *py); unsigned *px, unsigned *py);
typedef libvlc_event_manager_t *(*LIBVLC_MEDIA_PLAYER_EVENT_MANAGER)( typedef libvlc_event_manager_t *(*LIBVLC_MEDIA_PLAYER_EVENT_MANAGER)(
libvlc_media_player_t *p_mp); libvlc_media_player_t *p_mp);
typedef libvlc_state_t (*LIBVLC_MEDIA_PLAYER_GET_STATE)(
libvlc_media_player_t *p_mi);
typedef libvlc_time_t (*LIBVLC_MEDIA_PLAYER_GET_LENGTH)(
libvlc_media_player_t *p_mi);
/* libvlc media list */ /* libvlc media list */
typedef libvlc_media_list_t *(*LIBVLC_MEDIA_LIST_NEW)( typedef libvlc_media_list_t *(*LIBVLC_MEDIA_LIST_NEW)(
@ -124,8 +130,11 @@ extern LIBVLC_AUDIO_SET_FORMAT_CALLBACKS libvlc_audio_set_format_callbacks_;
extern LIBVLC_MEDIA_PLAYER_PLAY libvlc_media_player_play_; extern LIBVLC_MEDIA_PLAYER_PLAY libvlc_media_player_play_;
extern LIBVLC_MEDIA_PLAYER_STOP libvlc_media_player_stop_; extern LIBVLC_MEDIA_PLAYER_STOP libvlc_media_player_stop_;
extern LIBVLC_MEDIA_PLAYER_GET_TIME libvlc_media_player_get_time_; extern LIBVLC_MEDIA_PLAYER_GET_TIME libvlc_media_player_get_time_;
extern LIBVLC_MEDIA_PLAYER_SET_TIME libvlc_media_player_set_time_;
extern LIBVLC_VIDEO_GET_SIZE libvlc_video_get_size_; extern LIBVLC_VIDEO_GET_SIZE libvlc_video_get_size_;
extern LIBVLC_MEDIA_PLAYER_EVENT_MANAGER libvlc_media_player_event_manager_; extern LIBVLC_MEDIA_PLAYER_EVENT_MANAGER libvlc_media_player_event_manager_;
extern LIBVLC_MEDIA_PLAYER_GET_STATE libvlc_media_player_get_state_;
extern LIBVLC_MEDIA_PLAYER_GET_LENGTH libvlc_media_player_get_length_;
/* libvlc media list */ /* libvlc media list */
extern LIBVLC_MEDIA_LIST_NEW libvlc_media_list_new_; extern LIBVLC_MEDIA_LIST_NEW libvlc_media_list_new_;

View File

@ -661,20 +661,61 @@ static void vlcs_update(void *data, obs_data_t *settings)
obs_data_array_release(array); obs_data_array_release(array);
} }
static void vlcs_stopped(const struct libvlc_event_t *event, void *data) static void vlcs_started(const struct libvlc_event_t *event, void *data)
{ {
struct vlc_source *c = data; struct vlc_source *c = data;
if (!c->loop) obs_source_media_started(c->source);
obs_source_output_video(c->source, NULL);
UNUSED_PARAMETER(event); UNUSED_PARAMETER(event);
} }
static void vlcs_play_pause(void *data) static void vlcs_stopped(const struct libvlc_event_t *event, void *data)
{
struct vlc_source *c = data;
if (!c->loop) {
obs_source_output_video(c->source, NULL);
obs_source_media_ended(c->source);
}
UNUSED_PARAMETER(event);
}
static enum obs_media_state vlcs_get_state(void *data)
{ {
struct vlc_source *c = data; struct vlc_source *c = data;
libvlc_media_list_player_pause_(c->media_list_player); libvlc_state_t state = libvlc_media_player_get_state_(c->media_player);
switch (state) {
case libvlc_NothingSpecial:
return OBS_MEDIA_STATE_NONE;
case libvlc_Opening:
return OBS_MEDIA_STATE_OPENING;
case libvlc_Buffering:
return OBS_MEDIA_STATE_BUFFERING;
case libvlc_Playing:
return OBS_MEDIA_STATE_PLAYING;
case libvlc_Paused:
return OBS_MEDIA_STATE_PAUSED;
case libvlc_Stopped:
return OBS_MEDIA_STATE_STOPPED;
case libvlc_Ended:
return OBS_MEDIA_STATE_ENDED;
case libvlc_Error:
return OBS_MEDIA_STATE_ERROR;
}
return 0;
}
static void vlcs_play_pause(void *data, bool pause)
{
struct vlc_source *c = data;
if (pause)
libvlc_media_list_player_pause_(c->media_list_player);
else
libvlc_media_list_player_play_(c->media_list_player);
} }
static void vlcs_restart(void *data) static void vlcs_restart(void *data)
@ -707,6 +748,27 @@ static void vlcs_playlist_prev(void *data)
libvlc_media_list_player_previous_(c->media_list_player); libvlc_media_list_player_previous_(c->media_list_player);
} }
static int64_t vlcs_get_duration(void *data)
{
struct vlc_source *c = data;
return (int64_t)libvlc_media_player_get_length_(c->media_player);
}
static int64_t vlcs_get_time(void *data)
{
struct vlc_source *c = data;
return (int64_t)libvlc_media_player_get_time_(c->media_player);
}
static void vlcs_set_time(void *data, int64_t ms)
{
struct vlc_source *c = data;
libvlc_media_player_set_time_(c->media_player, (libvlc_time_t)ms);
}
static void vlcs_play_pause_hotkey(void *data, obs_hotkey_id id, static void vlcs_play_pause_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed) obs_hotkey_t *hotkey, bool pressed)
{ {
@ -715,8 +777,14 @@ static void vlcs_play_pause_hotkey(void *data, obs_hotkey_id id,
struct vlc_source *c = data; struct vlc_source *c = data;
if (pressed && obs_source_active(c->source)) enum obs_media_state state = obs_source_media_get_state(c->source);
vlcs_play_pause(c);
if (pressed && obs_source_active(c->source)) {
if (state == OBS_MEDIA_STATE_PLAYING)
obs_source_media_play_pause(c->source, true);
else if (state == OBS_MEDIA_STATE_PAUSED)
obs_source_media_play_pause(c->source, false);
}
} }
static void vlcs_restart_hotkey(void *data, obs_hotkey_id id, static void vlcs_restart_hotkey(void *data, obs_hotkey_id id,
@ -728,7 +796,7 @@ static void vlcs_restart_hotkey(void *data, obs_hotkey_id id,
struct vlc_source *c = data; struct vlc_source *c = data;
if (pressed && obs_source_active(c->source)) if (pressed && obs_source_active(c->source))
vlcs_restart(c); obs_source_media_restart(c->source);
} }
static void vlcs_stop_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, static void vlcs_stop_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
@ -740,7 +808,7 @@ static void vlcs_stop_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
struct vlc_source *c = data; struct vlc_source *c = data;
if (pressed && obs_source_active(c->source)) if (pressed && obs_source_active(c->source))
vlcs_stop(c); obs_source_media_stop(c->source);
} }
static void vlcs_playlist_next_hotkey(void *data, obs_hotkey_id id, static void vlcs_playlist_next_hotkey(void *data, obs_hotkey_id id,
@ -752,7 +820,7 @@ static void vlcs_playlist_next_hotkey(void *data, obs_hotkey_id id,
struct vlc_source *c = data; struct vlc_source *c = data;
if (pressed && obs_source_active(c->source)) if (pressed && obs_source_active(c->source))
vlcs_playlist_next(c); obs_source_media_next(c->source);
} }
static void vlcs_playlist_prev_hotkey(void *data, obs_hotkey_id id, static void vlcs_playlist_prev_hotkey(void *data, obs_hotkey_id id,
@ -764,7 +832,7 @@ static void vlcs_playlist_prev_hotkey(void *data, obs_hotkey_id id,
struct vlc_source *c = data; struct vlc_source *c = data;
if (pressed && obs_source_active(c->source)) if (pressed && obs_source_active(c->source))
vlcs_playlist_prev(c); obs_source_media_previous(c->source);
} }
static void *vlcs_create(obs_data_t *settings, obs_source_t *source) static void *vlcs_create(obs_data_t *settings, obs_source_t *source)
@ -824,6 +892,8 @@ static void *vlcs_create(obs_data_t *settings, obs_source_t *source)
event_manager = libvlc_media_player_event_manager_(c->media_player); event_manager = libvlc_media_player_event_manager_(c->media_player);
libvlc_event_attach_(event_manager, libvlc_MediaPlayerEndReached, libvlc_event_attach_(event_manager, libvlc_MediaPlayerEndReached,
vlcs_stopped, c); vlcs_stopped, c);
libvlc_event_attach_(event_manager, libvlc_MediaPlayerOpening,
vlcs_started, c);
obs_source_update(source, NULL); obs_source_update(source, NULL);
@ -952,7 +1022,8 @@ struct obs_source_info vlc_source_info = {
.id = "vlc_source", .id = "vlc_source",
.type = OBS_SOURCE_TYPE_INPUT, .type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | .output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO |
OBS_SOURCE_DO_NOT_DUPLICATE, OBS_SOURCE_DO_NOT_DUPLICATE |
OBS_SOURCE_CONTROLLABLE_MEDIA,
.get_name = vlcs_get_name, .get_name = vlcs_get_name,
.create = vlcs_create, .create = vlcs_create,
.destroy = vlcs_destroy, .destroy = vlcs_destroy,
@ -962,4 +1033,13 @@ struct obs_source_info vlc_source_info = {
.activate = vlcs_activate, .activate = vlcs_activate,
.deactivate = vlcs_deactivate, .deactivate = vlcs_deactivate,
.icon_type = OBS_ICON_TYPE_MEDIA, .icon_type = OBS_ICON_TYPE_MEDIA,
.media_play_pause = vlcs_play_pause,
.media_restart = vlcs_restart,
.media_stop = vlcs_stop,
.media_next = vlcs_playlist_next,
.media_previous = vlcs_playlist_prev,
.media_get_duration = vlcs_get_duration,
.media_get_time = vlcs_get_time,
.media_set_time = vlcs_set_time,
.media_get_state = vlcs_get_state,
}; };