summaryrefslogtreecommitdiffstats
path: root/player/playloop.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-02-05 23:19:56 +0100
committerwm4 <wm4@nowhere>2016-02-05 23:19:56 +0100
commitc0de087ba191a4daf3a152e0ab09b5687fab8449 (patch)
treeb00043c5e4055ef777a0afdba6b4a321e87864de /player/playloop.c
parent45345d9c41f1491e9809153dc3b3950fba560d89 (diff)
downloadmpv-c0de087ba191a4daf3a152e0ab09b5687fab8449.tar.bz2
mpv-c0de087ba191a4daf3a152e0ab09b5687fab8449.tar.xz
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)
Diffstat (limited to 'player/playloop.c')
-rw-r--r--player/playloop.c53
1 files changed, 53 insertions, 0 deletions
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.