diff options
Diffstat (limited to 'player')
-rw-r--r-- | player/audio.c | 220 | ||||
-rw-r--r-- | player/command.c | 5 | ||||
-rw-r--r-- | player/core.h | 10 | ||||
-rw-r--r-- | player/loadfile.c | 30 | ||||
-rw-r--r-- | player/main.c | 1 | ||||
-rw-r--r-- | player/playloop.c | 38 | ||||
-rw-r--r-- | player/video.c | 1 |
7 files changed, 75 insertions, 230 deletions
diff --git a/player/audio.c b/player/audio.c index ab53ab3b86..5b061efca1 100644 --- a/player/audio.c +++ b/player/audio.c @@ -33,21 +33,17 @@ #include "audio/audio_buffer.h" #include "audio/format.h" -#include "audio/decode/dec_audio.h" #include "audio/out/ao.h" #include "demux/demux.h" +#include "filters/f_decoder_wrapper.h" #include "core.h" #include "command.h" enum { AD_OK = 0, - AD_ERR = -1, AD_EOF = -2, - AD_NEW_FMT = -3, AD_WAIT = -4, - AD_NO_PROGRESS = -5, - AD_STARVE = -6, }; // Try to reuse the existing filters to change playback speed. If it works, @@ -183,17 +179,11 @@ void update_playback_speed(struct MPContext *mpctx) static void ao_chain_reset_state(struct ao_chain *ao_c) { ao_c->last_out_pts = MP_NOPTS_VALUE; - ao_c->pts = MP_NOPTS_VALUE; ao_c->pts_reset = false; - TA_FREEP(&ao_c->input_frame); TA_FREEP(&ao_c->output_frame); + ao_c->out_eof = false; mp_audio_buffer_clear(ao_c->ao_buffer); - - if (ao_c->audio_src) - audio_reset_decoding(ao_c->audio_src); - - ao_c->filter_src_got_eof = false; } void reset_audio_state(struct MPContext *mpctx) @@ -226,16 +216,16 @@ static void ao_chain_uninit(struct ao_chain *ao_c) if (track) { assert(track->ao_c == ao_c); track->ao_c = NULL; - assert(track->d_audio == ao_c->audio_src); - track->d_audio = NULL; - audio_uninit(ao_c->audio_src); + if (ao_c->dec_src) + assert(track->dec->f->pins[0] == ao_c->dec_src); + talloc_free(track->dec->f); + track->dec = NULL; } if (ao_c->filter_src) mp_pin_disconnect(ao_c->filter_src); talloc_free(ao_c->filter->f); - talloc_free(ao_c->input_frame); talloc_free(ao_c->output_frame); talloc_free(ao_c->ao_buffer); talloc_free(ao_c); @@ -361,12 +351,12 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx) if (!mpctx->ao) { // If spdif was used, try to fallback to PCM. - if (spdif_fallback && ao_c->audio_src) { + if (spdif_fallback && ao_c->track && ao_c->track->dec) { MP_VERBOSE(mpctx, "Falling back to PCM output.\n"); ao_c->spdif_passthrough = false; ao_c->spdif_failed = true; - ao_c->audio_src->try_spdif = false; - if (!audio_init_best_codec(ao_c->audio_src)) + ao_c->track->dec->try_spdif = false; + if (!mp_decoder_wrapper_reinit(ao_c->track->dec)) goto init_error; reset_audio_state(mpctx); mp_output_chain_reset_harder(ao_c->filter); @@ -408,21 +398,18 @@ init_error: int init_audio_decoder(struct MPContext *mpctx, struct track *track) { - assert(!track->d_audio); + assert(!track->dec); if (!track->stream) goto init_error; - track->d_audio = talloc_zero(NULL, struct dec_audio); - struct dec_audio *d_audio = track->d_audio; - d_audio->log = mp_log_new(d_audio, mpctx->log, "!ad"); - d_audio->global = mpctx->global; - d_audio->opts = mpctx->opts; - d_audio->header = track->stream; - d_audio->codec = track->stream->codec; + track->dec = mp_decoder_wrapper_create(mpctx->filter_root, track->stream); + if (!track->dec) + goto init_error; - d_audio->try_spdif = true; + if (track->ao_c) + track->dec->try_spdif = true; - if (!audio_init_best_codec(d_audio)) + if (!mp_decoder_wrapper_reinit(track->dec)) goto init_error; return 1; @@ -431,8 +418,6 @@ init_error: if (track->sink) mp_pin_disconnect(track->sink); track->sink = NULL; - audio_uninit(track->d_audio); - track->d_audio = NULL; error_on_track(mpctx, track); return 0; } @@ -462,7 +447,7 @@ void reinit_audio_chain_src(struct MPContext *mpctx, struct track *track) ao_c->filter = mp_output_chain_create(mpctx->filter_root, MP_OUTPUT_CHAIN_AUDIO); ao_c->spdif_passthrough = true; - ao_c->pts = MP_NOPTS_VALUE; + ao_c->last_out_pts = MP_NOPTS_VALUE; ao_c->ao_buffer = mp_audio_buffer_create(NULL); ao_c->ao = mpctx->ao; @@ -471,7 +456,8 @@ void reinit_audio_chain_src(struct MPContext *mpctx, struct track *track) track->ao_c = ao_c; if (!init_audio_decoder(mpctx, track)) goto init_error; - ao_c->audio_src = track->d_audio; + ao_c->dec_src = track->dec->f->pins[0]; + mp_pin_connect(ao_c->filter->f->pins[0], ao_c->dec_src); } reset_audio_state(mpctx); @@ -643,7 +629,7 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip) static bool copy_output(struct MPContext *mpctx, struct ao_chain *ao_c, - int minsamples, double endpts, bool eof, bool *seteof) + int minsamples, double endpts, bool *seteof) { struct mp_audio_buffer *outbuf = ao_c->ao_buffer; @@ -671,16 +657,39 @@ static bool copy_output(struct MPContext *mpctx, struct ao_chain *ao_c, struct mp_frame frame = mp_pin_out_read(ao_c->filter->f->pins[1]); if (frame.type == MP_FRAME_AUDIO) { ao_c->output_frame = frame.data; + ao_c->out_eof = false; + + double pts = mp_aframe_get_pts(ao_c->output_frame); + if (pts != MP_NOPTS_VALUE) { + // Attempt to detect jumps in PTS. Even for the lowest + // sample rates and with worst container rounded timestamp, + // this should be a margin more than enough. + double desync = pts - ao_c->last_out_pts; + if (ao_c->last_out_pts != MP_NOPTS_VALUE && fabs(desync) > 0.1) + { + MP_WARN(ao_c, "Invalid audio PTS: %f -> %f\n", + ao_c->last_out_pts, pts); + if (desync >= 5) + ao_c->pts_reset = true; + } + } ao_c->last_out_pts = mp_aframe_end_pts(ao_c->output_frame); } else if (frame.type == MP_FRAME_EOF) { - *seteof = true; + ao_c->out_eof = true; } else if (frame.type) { MP_ERR(mpctx, "unknown frame type\n"); + mp_frame_unref(&frame); } } - if (!ao_c->output_frame) - return false; // out of data + // out of data + if (!ao_c->output_frame) { + if (ao_c->out_eof) { + *seteof = true; + return true; + } + return false; + } if (cursamples + mp_aframe_get_size(ao_c->output_frame) > maxsamples) { if (cursamples < maxsamples) { @@ -702,43 +711,6 @@ static bool copy_output(struct MPContext *mpctx, struct ao_chain *ao_c, return true; } -static int decode_new_frame(struct ao_chain *ao_c) -{ - if (ao_c->input_frame) - return AD_OK; - - int res = DATA_EOF; - if (ao_c->filter_src) { - struct mp_frame frame = mp_pin_out_read(ao_c->filter_src); - if (frame.type == MP_FRAME_EOF) { - res = DATA_EOF; - ao_c->filter_src_got_eof = true; - } else if (frame.type == MP_FRAME_AUDIO) { - res = DATA_OK; - ao_c->input_frame = frame.data; - ao_c->filter_src_got_eof = false; - } else if (frame.type) { - MP_ERR(ao_c, "unexpected frame type\n"); - mp_frame_unref(&frame); - res = DATA_EOF; - } else { - res = ao_c->filter_src_got_eof ? DATA_EOF : DATA_WAIT; - } - } else if (ao_c->audio_src) { - audio_work(ao_c->audio_src); - res = audio_get_frame(ao_c->audio_src, &ao_c->input_frame); - } - - switch (res) { - case DATA_OK: return AD_OK; - case DATA_WAIT: return AD_WAIT; - case DATA_AGAIN: return AD_NO_PROGRESS; - case DATA_STARVE: return AD_STARVE; - case DATA_EOF: return AD_EOF; - default: abort(); - } -} - /* Try to get at least minsamples decoded+filtered samples in outbuf * (total length including possible existing data). * Return 0 on success, or negative AD_* error code. @@ -749,64 +721,12 @@ static int filter_audio(struct MPContext *mpctx, struct mp_audio_buffer *outbuf, { struct ao_chain *ao_c = mpctx->ao_chain; - MP_STATS(ao_c, "start audio"); - double endpts = get_play_end_pts(mpctx); bool eof = false; - int res; - while (1) { - res = 0; - - if (copy_output(mpctx, ao_c, minsamples, endpts, false, &eof)) - break; - - res = decode_new_frame(ao_c); - if (res == AD_NO_PROGRESS) - continue; - if (res == AD_WAIT || res == AD_STARVE) - break; - if (res < 0) { - // drain filters first (especially for true EOF case) - if (!ao_c->filter->got_input_eof) - mp_pin_in_write(ao_c->filter->f->pins[0], MP_EOF_FRAME); - copy_output(mpctx, ao_c, minsamples, endpts, true, &eof); - break; - } - assert(ao_c->input_frame); - - double pts = mp_aframe_get_pts(ao_c->input_frame); - if (pts == MP_NOPTS_VALUE) { - ao_c->pts = MP_NOPTS_VALUE; - } else { - // Attempt to detect jumps in PTS. Even for the lowest sample rates - // and with worst container rounded timestamp, this should be a - // margin more than enough. - double desync = pts - ao_c->pts; - if (ao_c->pts != MP_NOPTS_VALUE && fabs(desync) > 0.1) { - MP_WARN(ao_c, "Invalid audio PTS: %f -> %f\n", - ao_c->pts, pts); - if (desync >= 5) - ao_c->pts_reset = true; - } - ao_c->pts = mp_aframe_end_pts(ao_c->input_frame); - } - - if (!mp_pin_in_needs_data(ao_c->filter->f->pins[0])) { - res = AD_WAIT; - break; - } - mp_pin_in_write(ao_c->filter->f->pins[0], - MAKE_FRAME(MP_FRAME_AUDIO, ao_c->input_frame)); - ao_c->input_frame = NULL; - } - - if (res == 0 && mp_audio_buffer_samples(outbuf) < minsamples && eof) - res = AD_EOF; - - MP_STATS(ao_c, "end audio"); - - return res; + if (!copy_output(mpctx, ao_c, minsamples, endpts, &eof)) + return AD_WAIT; + return eof ? AD_EOF : AD_OK; } void reload_audio_output(struct MPContext *mpctx) @@ -818,17 +738,23 @@ void reload_audio_output(struct MPContext *mpctx) uninit_audio_out(mpctx); reinit_audio_filters(mpctx); // mostly to issue refresh seek + struct ao_chain *ao_c = mpctx->ao_chain; + + if (ao_c) { + reset_audio_state(mpctx); + mp_output_chain_reset_harder(ao_c->filter); + } + // Whether we can use spdif might have changed. If we failed to use spdif // in the previous initialization, try it with spdif again (we'll fallback // to PCM again if necessary). - struct ao_chain *ao_c = mpctx->ao_chain; - if (ao_c) { - struct dec_audio *d_audio = ao_c->audio_src; - if (d_audio && ao_c->spdif_failed) { + if (ao_c && ao_c->track) { + struct mp_decoder_wrapper *dec = ao_c->track->dec; + if (dec && ao_c->spdif_failed) { ao_c->spdif_passthrough = true; ao_c->spdif_failed = false; - d_audio->try_spdif = true; - if (!audio_init_best_codec(d_audio)) { + dec->try_spdif = true; + if (!mp_decoder_wrapper_reinit(dec)) { MP_ERR(mpctx, "Error reinitializing audio.\n"); error_on_track(mpctx, ao_c->track); } @@ -857,29 +783,13 @@ void fill_audio_out_buffers(struct MPContext *mpctx) return; } - if (ao_c->input_frame && mp_pin_in_needs_data(ao_c->filter->f->pins[0])) { - mp_pin_in_write(ao_c->filter->f->pins[0], - MAKE_FRAME(MP_FRAME_AUDIO, ao_c->input_frame)); - ao_c->input_frame = NULL; - } - // (if AO is set due to gapless from previous file, then we can try to // filter normally until the filter tells us to change the AO) if (!mpctx->ao) { - mp_pin_out_request_data(ao_c->filter->f->pins[1]); // Probe the initial audio format. Returns AD_OK (and does nothing) if // the format is already known. - int r = AD_NO_PROGRESS; - while (r == AD_NO_PROGRESS) - r = decode_new_frame(mpctx->ao_chain); - if (r == AD_WAIT) - return; // continue later when new data is available - if (r == AD_EOF) { - mpctx->audio_status = STATUS_EOF; - return; - } + mp_pin_out_request_data(ao_c->filter->f->pins[1]); reinit_audio_filters_and_output(mpctx); - mp_wakeup_core(mpctx); return; // try again next iteration } @@ -949,12 +859,6 @@ void fill_audio_out_buffers(struct MPContext *mpctx) } if (status == AD_WAIT) return; - if (status == AD_NO_PROGRESS || status == AD_STARVE) { - mp_wakeup_core(mpctx); - return; - } - if (status == AD_ERR) - mp_wakeup_core(mpctx); working = true; } diff --git a/player/command.c b/player/command.c index d1de5a86ff..1b074b8767 100644 --- a/player/command.c +++ b/player/command.c @@ -57,7 +57,6 @@ #include "audio/aframe.h" #include "audio/format.h" #include "audio/out/ao.h" -#include "audio/decode/dec_audio.h" #include "video/out/bitmap_packer.h" #include "options/path.h" #include "screenshot.h" @@ -2038,7 +2037,7 @@ static int mp_property_audio_codec(void *ctx, struct m_property *prop, { MPContext *mpctx = ctx; struct track *track = mpctx->current_track[0][STREAM_AUDIO]; - const char *c = track && track->d_audio ? track->d_audio->decoder_desc : NULL; + const char *c = track && track->dec ? track->dec->decoder_desc : NULL; return m_property_strdup_ro(action, arg, c); } @@ -2186,8 +2185,6 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) const char *decoder_desc = NULL; if (track->dec) decoder_desc = track->dec->decoder_desc; - if (track->d_audio) - decoder_desc = track->d_audio->decoder_desc; bool has_rg = track->stream && track->stream->codec->replaygain_data; struct replaygain_data rg = has_rg ? *track->stream->codec->replaygain_data diff --git a/player/core.h b/player/core.h index f27c30b145..8a77690de6 100644 --- a/player/core.h +++ b/player/core.h @@ -154,13 +154,11 @@ struct track { // Current decoding state (NULL if selected==false) struct mp_decoder_wrapper *dec; - struct dec_audio *d_audio; // Where the decoded result goes to (one of them is not NULL if active) struct vo_chain *vo_c; struct ao_chain *ao_c; struct mp_pin *sink; - bool sink_eof; // whether it got passed EOF // For stream recording (remuxing mode). struct mp_recorder_sink *remux_sink; @@ -190,7 +188,6 @@ struct vo_chain { struct ao_chain { struct mp_log *log; - double pts; // timestamp of first sample output by decoder bool spdif_passthrough, spdif_failed; bool pts_reset; @@ -200,18 +197,15 @@ struct ao_chain { struct mp_audio_buffer *ao_buffer; double ao_resume_time; - // 1-element input frame queue. - struct mp_aframe *input_frame; - // 1-element output frame queue. struct mp_aframe *output_frame; + bool out_eof; double last_out_pts; struct track *track; struct mp_pin *filter_src; - bool filter_src_got_eof; // whether this returned EOF last time - struct dec_audio *audio_src; + struct mp_pin *dec_src; }; /* Note that playback can be paused, stopped, etc. at any time. While paused, diff --git a/player/loadfile.c b/player/loadfile.c index d35ae6ad6b..44f0f970ac 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -43,7 +43,6 @@ #include "common/recorder.h" #include "input/input.h" -#include "audio/decode/dec_audio.h" #include "audio/out/ao.h" #include "filters/f_decoder_wrapper.h" #include "filters/f_lavfi.h" @@ -984,14 +983,10 @@ static void cleanup_deassociated_complex_filters(struct MPContext *mpctx) for (int n = 0; n < mpctx->num_tracks; n++) { struct track *track = mpctx->tracks[n]; if (!(track->sink || track->vo_c || track->ao_c)) { - if (track->dec && !track->vo_c) { + if (track->dec && !track->vo_c && !track->ao_c) { talloc_free(track->dec->f); track->dec->f = NULL; } - if (track->d_audio && !track->ao_c) { - audio_uninit(track->d_audio); - track->d_audio = NULL; - } track->selected = false; } } @@ -1001,7 +996,7 @@ static void cleanup_deassociated_complex_filters(struct MPContext *mpctx) { uninit_video_chain(mpctx); } - if (mpctx->ao_chain && !mpctx->ao_chain->audio_src && + if (mpctx->ao_chain && !mpctx->ao_chain->dec_src && !mpctx->ao_chain->filter_src) { uninit_audio_chain(mpctx); @@ -1094,17 +1089,16 @@ static int reinit_complex_filters(struct MPContext *mpctx, bool force_uninit) pad = mp_filter_get_named_pin(mpctx->lavfi, "ao"); if (pad && mp_pin_get_dir(pad) == MP_PIN_OUT) { if (mpctx->ao_chain) { - if (mpctx->ao_chain->audio_src) { - MP_ERR(mpctx, "Pad ao tries to connect to already used AO.\n"); - goto done; - } + MP_ERR(mpctx, "Pad ao tries to connect to already used AO.\n"); + goto done; } else { reinit_audio_chain_src(mpctx, NULL); if (!mpctx->ao_chain) goto done; } - mp_pin_set_manual_connection(pad, true); - mpctx->ao_chain->filter_src = pad; + struct ao_chain *ao_c = mpctx->ao_chain; + ao_c->filter_src = pad; + mp_pin_connect(ao_c->filter->f->pins[0], ao_c->filter_src); } for (int n = 0; n < mpctx->num_tracks; n++) { @@ -1115,8 +1109,9 @@ static int reinit_complex_filters(struct MPContext *mpctx, bool force_uninit) mp_pin_connect(track->sink, track->dec->f->pins[0]); } if (track->sink && track->type == STREAM_AUDIO) { - if (!track->d_audio && !init_audio_decoder(mpctx, track)) + if (!track->dec && !init_audio_decoder(mpctx, track)) goto done; + mp_pin_connect(track->sink, track->dec->f->pins[0]); } } @@ -1588,8 +1583,6 @@ static void set_track_recorder_sink(struct track *track, sub_set_recorder_sink(track->d_sub, sink); if (track->dec) track->dec->recorder_sink = sink; - if (track->d_audio) - track->d_audio->recorder_sink = sink; track->remux_sink = sink; } @@ -1631,11 +1624,8 @@ void open_recorder(struct MPContext *mpctx, bool on_init) for (int n = 0; n < mpctx->num_tracks; n++) { struct track *track = mpctx->tracks[n]; - if (track->stream && track->selected && - (track->d_sub || track->dec || track->d_audio)) - { + if (track->stream && track->selected && (track->d_sub || track->dec)) MP_TARRAY_APPEND(NULL, streams, num_streams, track->stream); - } } mpctx->recorder = mp_recorder_create(mpctx->global, mpctx->opts->record_file, diff --git a/player/main.c b/player/main.c index 98abbc8e4f..711b413735 100644 --- a/player/main.c +++ b/player/main.c @@ -50,7 +50,6 @@ #include "options/path.h" #include "input/input.h" -#include "audio/decode/dec_audio.h" #include "audio/out/ao.h" #include "demux/demux.h" #include "stream/stream.h" diff --git a/player/playloop.c b/player/playloop.c index 748469354d..e77200f2d7 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -39,7 +39,6 @@ #include "osdep/terminal.h" #include "osdep/timer.h" -#include "audio/decode/dec_audio.h" #include "audio/out/ao.h" #include "demux/demux.h" #include "stream/stream.h" @@ -212,12 +211,6 @@ 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) { - for (int n = 0; n < mpctx->num_tracks; n++) { - if (mpctx->tracks[n]->d_audio) - audio_reset_decoding(mpctx->tracks[n]->d_audio); - mpctx->tracks[n]->sink_eof = false; - } - mp_filter_reset(mpctx->filter_root); reset_video_state(mpctx); @@ -1076,35 +1069,6 @@ static void handle_eof(struct MPContext *mpctx) } } -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->d_audio) { - if (!track->sink || !mp_pin_in_needs_data(track->sink)) - continue; - audio_work(track->d_audio); - struct mp_aframe *fr; - int res = audio_get_frame(track->d_audio, &fr); - if (res == DATA_OK) { - mp_pin_in_write(track->sink, MAKE_FRAME(MP_FRAME_AUDIO, fr)); - track->sink_eof = false; - } else if (res == DATA_EOF) { - if (!track->sink_eof) - mp_pin_in_write(track->sink, MP_EOF_FRAME); - track->sink_eof = true; - } else if (res == DATA_AGAIN) { - mp_wakeup_core(mpctx); - } - } - } -} - void run_playloop(struct MPContext *mpctx) { #if HAVE_ENCODING @@ -1116,8 +1080,6 @@ void run_playloop(struct MPContext *mpctx) update_demuxer_properties(mpctx); - handle_complex_filter_decoders(mpctx); - handle_cursor_autohide(mpctx); handle_vo_events(mpctx); handle_command_updates(mpctx); diff --git a/player/video.c b/player/video.c index 48b02ecec7..619c73e3f1 100644 --- a/player/video.c +++ b/player/video.c @@ -41,7 +41,6 @@ #include "video/hwdec.h" #include "filters/f_decoder_wrapper.h" #include "video/out/vo.h" -#include "audio/decode/dec_audio.h" #include "core.h" #include "command.h" |