From c0de087ba191a4daf3a152e0ab09b5687fab8449 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 5 Feb 2016 23:19:56 +0100 Subject: player: add complex filter graph support See --lavfi-complex option. This is still quite rough. There's no support for dynamic configuration of any kind. There are probably corner cases where playback might freeze or burn 100% CPU (due to dataflow problems when interaction with libavfilter). Future possible plans might include: - freely switch tracks by providing some sort of default track graph label - automatically enabling audio visualization - automatically mix audio or stack video when multiple tracks are selected at once (similar to how multiple sub tracks can be selected) --- player/playloop.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'player/playloop.c') diff --git a/player/playloop.c b/player/playloop.c index 6f4521b32a..9fd465b6a2 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -151,6 +151,16 @@ void add_step_frame(struct MPContext *mpctx, int dir) // Clear some playback-related fields on file loading or after seeks. void reset_playback_state(struct MPContext *mpctx) { + if (mpctx->lavfi) + lavfi_seek_reset(mpctx->lavfi); + + for (int n = 0; n < mpctx->num_tracks; n++) { + if (mpctx->tracks[n]->d_video) + video_reset(mpctx->tracks[n]->d_video); + if (mpctx->tracks[n]->d_audio) + audio_reset_decoding(mpctx->tracks[n]->d_audio); + } + reset_video_state(mpctx); reset_audio_state(mpctx); reset_subtitle_state(mpctx); @@ -922,6 +932,40 @@ static void handle_segment_switch(struct MPContext *mpctx, bool end_is_new_segme } } +static void handle_complex_filter_decoders(struct MPContext *mpctx) +{ + if (!mpctx->lavfi) + return; + + for (int n = 0; n < mpctx->num_tracks; n++) { + struct track *track = mpctx->tracks[n]; + if (!track->selected) + continue; + if (!track->sink || !lavfi_needs_input(track->sink)) + continue; + if (track->d_audio) { + audio_work(track->d_audio); + struct mp_audio *fr; + int res = audio_get_frame(track->d_audio, &fr); + if (res == DATA_OK) { + lavfi_send_frame_a(track->sink, fr); + } else { + lavfi_send_status(track->sink, res); + } + } + if (track->d_video) { + video_work(track->d_video); + struct mp_image *fr; + int res = video_get_frame(track->d_video, &fr); + if (res == DATA_OK) { + lavfi_send_frame_v(track->sink, fr); + } else { + lavfi_send_status(track->sink, res); + } + } + } +} + void run_playloop(struct MPContext *mpctx) { double endpts = get_play_end_pts(mpctx); @@ -944,6 +988,8 @@ void run_playloop(struct MPContext *mpctx) } } + handle_complex_filter_decoders(mpctx); + handle_cursor_autohide(mpctx); handle_vo_events(mpctx); handle_heartbeat_cmd(mpctx); @@ -952,6 +998,13 @@ void run_playloop(struct MPContext *mpctx) fill_audio_out_buffers(mpctx, endpts); write_video(mpctx, endpts); + if (mpctx->lavfi) { + if (lavfi_process(mpctx->lavfi)) + mpctx->sleeptime = 0; + if (lavfi_has_failed(mpctx->lavfi)) + mpctx->stop_play = AT_END_OF_FILE; + } + handle_playback_restart(mpctx, endpts); // Use the audio timestamp if no video, or video is enabled, but has ended. -- cgit v1.2.3