diff --git a/audio/decode/ad.h b/audio/decode/ad.h deleted file mode 100644 index a8384c277f..0000000000 --- a/audio/decode/ad.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#ifndef MPLAYER_AD_H -#define MPLAYER_AD_H - -#include "common/codecs.h" -#include "demux/stheader.h" -#include "demux/demux.h" - -#include "audio/format.h" -#include "audio/aframe.h" -#include "dec_audio.h" - -struct mp_decoder_list; - -/* interface of audio decoder drivers */ -struct ad_functions { - const char *name; - void (*add_decoders)(struct mp_decoder_list *list); - int (*init)(struct dec_audio *da, const char *decoder); - void (*uninit)(struct dec_audio *da); - int (*control)(struct dec_audio *da, int cmd, void *arg); - // Return whether or not the packet has been consumed. - bool (*send_packet)(struct dec_audio *da, struct demux_packet *pkt); - // Return whether decoding is still going on (false if EOF was reached). - // Never returns false & *out set, but can return true with !*out. - bool (*receive_frame)(struct dec_audio *da, struct mp_aframe **out); -}; - -enum ad_ctrl { - ADCTRL_RESET = 1, // flush and reset state, e.g. after seeking -}; - -#endif /* MPLAYER_AD_H */ diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index fb429d567b..7713a506a6 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -27,27 +27,30 @@ #include #include "mpv_talloc.h" - -#include "config.h" +#include "audio/aframe.h" +#include "audio/fmt-conversion.h" #include "common/av_common.h" #include "common/codecs.h" +#include "common/global.h" #include "common/msg.h" +#include "demux/packet.h" +#include "demux/stheader.h" +#include "filters/f_decoder_wrapper.h" +#include "filters/filter_internal.h" #include "options/options.h" -#include "ad.h" -#include "audio/fmt-conversion.h" - struct priv { AVCodecContext *avctx; AVFrame *avframe; - bool force_channel_map; + struct mp_chmap force_channel_map; uint32_t skip_samples, trim_samples; bool preroll_done; double next_pts; AVRational codec_timebase; -}; + bool eof_returned; -static void uninit(struct dec_audio *da); + struct mp_decoder public; +}; #define OPT_BASE_STRUCT struct ad_lavc_params struct ad_lavc_params { @@ -73,26 +76,24 @@ const struct m_sub_options ad_lavc_conf = { }, }; -static int init(struct dec_audio *da, const char *decoder) +static bool init(struct mp_filter *da, struct mp_codec_params *codec, + const char *decoder) { - struct MPOpts *mpopts = da->opts; + struct priv *ctx = da->priv; + struct MPOpts *mpopts = da->global->opts; struct ad_lavc_params *opts = mpopts->ad_lavc_params; AVCodecContext *lavc_context; AVCodec *lavc_codec; - struct mp_codec_params *c = da->codec; - struct priv *ctx = talloc_zero(NULL, struct priv); - da->priv = ctx; + ctx->codec_timebase = mp_get_codec_timebase(codec); - ctx->codec_timebase = mp_get_codec_timebase(da->codec); - - ctx->force_channel_map = c->force_channels; + if (codec->force_channels) + ctx->force_channel_map = codec->channels; lavc_codec = avcodec_find_decoder_by_name(decoder); if (!lavc_codec) { MP_ERR(da, "Cannot find codec '%s' in libavcodec...\n", decoder); - uninit(da); - return 0; + return false; } lavc_context = avcodec_alloc_context3(lavc_codec); @@ -121,10 +122,9 @@ static int init(struct dec_audio *da, const char *decoder) mp_set_avopts(da->log, lavc_context, opts->avopts); - if (mp_set_avctx_codec_headers(lavc_context, c) < 0) { + if (mp_set_avctx_codec_headers(lavc_context, codec) < 0) { MP_ERR(da, "Could not set decoder parameters.\n"); - uninit(da); - return 0; + return false; } mp_set_avcodec_threads(da->log, lavc_context, opts->threads); @@ -132,41 +132,35 @@ static int init(struct dec_audio *da, const char *decoder) /* open it */ if (avcodec_open2(lavc_context, lavc_codec, NULL) < 0) { MP_ERR(da, "Could not open codec.\n"); - uninit(da); - return 0; + return false; } ctx->next_pts = MP_NOPTS_VALUE; - return 1; + return true; } -static void uninit(struct dec_audio *da) +static void destroy(struct mp_filter *da) { struct priv *ctx = da->priv; - if (!ctx) - return; avcodec_free_context(&ctx->avctx); av_frame_free(&ctx->avframe); } -static int control(struct dec_audio *da, int cmd, void *arg) +static void reset(struct mp_filter *da) { struct priv *ctx = da->priv; - switch (cmd) { - case ADCTRL_RESET: - avcodec_flush_buffers(ctx->avctx); - ctx->skip_samples = 0; - ctx->trim_samples = 0; - ctx->preroll_done = false; - ctx->next_pts = MP_NOPTS_VALUE; - return CONTROL_TRUE; - } - return CONTROL_UNKNOWN; + + avcodec_flush_buffers(ctx->avctx); + ctx->skip_samples = 0; + ctx->trim_samples = 0; + ctx->preroll_done = false; + ctx->next_pts = MP_NOPTS_VALUE; + ctx->eof_returned = false; } -static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt) +static bool send_packet(struct mp_filter *da, struct demux_packet *mpkt) { struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; @@ -190,7 +184,7 @@ static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt) return true; } -static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) +static bool receive_frame(struct mp_filter *da, struct mp_frame *out) { struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; @@ -200,7 +194,8 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) if (ret == AVERROR_EOF) { // If flushing was initialized earlier and has ended now, make it start // over in case we get new packets at some point in the future. - control(da, ADCTRL_RESET, NULL); + // (Dont' reset the filter itself, we want to keep other state.) + avcodec_flush_buffers(priv->avctx); return false; } else if (ret < 0 && ret != AVERROR(EAGAIN)) { MP_ERR(da, "Error decoding audio.\n"); @@ -220,8 +215,8 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) if (!mpframe) return true; - if (priv->force_channel_map) - mp_aframe_set_chmap(mpframe, &da->codec->channels); + if (priv->force_channel_map.num) + mp_aframe_set_chmap(mpframe, &priv->force_channel_map); if (out_pts == MP_NOPTS_VALUE) out_pts = priv->next_pts; @@ -257,24 +252,57 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) priv->trim_samples -= trim; } - *out = mpframe; + *out = MAKE_FRAME(MP_FRAME_AUDIO, mpframe); av_frame_unref(priv->avframe); return true; } +static void process(struct mp_filter *ad) +{ + struct priv *priv = ad->priv; + + lavc_process(ad, &priv->eof_returned, send_packet, receive_frame); +} + +static const struct mp_filter_info ad_lavc_filter = { + .name = "ad_lavc", + .priv_size = sizeof(struct priv), + .process = process, + .reset = reset, + .destroy = destroy, +}; + +static struct mp_decoder *create(struct mp_filter *parent, + struct mp_codec_params *codec, + const char *decoder) +{ + struct mp_filter *da = mp_filter_create(parent, &ad_lavc_filter); + if (!da) + return NULL; + + mp_filter_add_pin(da, MP_PIN_IN, "in"); + mp_filter_add_pin(da, MP_PIN_OUT, "out"); + + da->log = mp_log_new(da, parent->log, NULL); + + struct priv *priv = da->priv; + priv->public.f = da; + + if (!init(da, codec, decoder)) { + talloc_free(da); + return NULL; + } + return &priv->public; +} + static void add_decoders(struct mp_decoder_list *list) { mp_add_lavc_decoders(list, AVMEDIA_TYPE_AUDIO); } -const struct ad_functions ad_lavc = { - .name = "lavc", +const struct mp_decoder_fns ad_lavc = { + .create = create, .add_decoders = add_decoders, - .init = init, - .uninit = uninit, - .control = control, - .send_packet = send_packet, - .receive_frame = receive_frame, }; diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index cc800224e9..c97c62ddaa 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -24,11 +24,16 @@ #include #include -#include "config.h" -#include "common/msg.h" +#include "audio/aframe.h" +#include "audio/format.h" #include "common/av_common.h" +#include "common/codecs.h" +#include "common/msg.h" +#include "demux/packet.h" +#include "demux/stheader.h" +#include "filters/f_decoder_wrapper.h" +#include "filters/filter_internal.h" #include "options/options.h" -#include "ad.h" #define OUTBUF_SIZE 65536 @@ -43,8 +48,8 @@ struct spdifContext { struct mp_aframe *fmt; int sstride; struct mp_aframe_pool *pool; - bool got_eof; - struct demux_packet *queued_packet; + + struct mp_decoder public; }; static int write_packet(void *p, uint8_t *buf, int buf_size) @@ -62,7 +67,8 @@ static int write_packet(void *p, uint8_t *buf, int buf_size) return buf_size; } -static void uninit(struct dec_audio *da) +// (called on both filter destruction _and_ if lavf fails to init) +static void destroy(struct mp_filter *da) { struct spdifContext *spdif_ctx = da->priv; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; @@ -74,26 +80,11 @@ static void uninit(struct dec_audio *da) av_freep(&lavf_ctx->pb->buffer); av_freep(&lavf_ctx->pb); avformat_free_context(lavf_ctx); - talloc_free(spdif_ctx->queued_packet); spdif_ctx->lavf_ctx = NULL; } } -static int init(struct dec_audio *da, const char *decoder) -{ - struct spdifContext *spdif_ctx = talloc_zero(NULL, struct spdifContext); - da->priv = spdif_ctx; - spdif_ctx->log = da->log; - spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx); - - if (strcmp(decoder, "spdif_dts_hd") == 0) - spdif_ctx->use_dts_hd = true; - - spdif_ctx->codec_id = mp_codec_to_av_codec_id(da->codec->codec); - return spdif_ctx->codec_id != AV_CODEC_ID_NONE; -} - -static void determine_codec_params(struct dec_audio *da, AVPacket *pkt, +static void determine_codec_params(struct mp_filter *da, AVPacket *pkt, int *out_profile, int *out_rate) { struct spdifContext *spdif_ctx = da->priv; @@ -156,7 +147,7 @@ done: MP_WARN(da, "Failed to parse codec profile.\n"); } -static int init_filter(struct dec_audio *da, AVPacket *pkt) +static int init_filter(struct mp_filter *da, AVPacket *pkt) { struct spdifContext *spdif_ctx = da->priv; @@ -270,39 +261,36 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt) return 0; fail: - uninit(da); + destroy(da); + mp_filter_internal_mark_failed(da); return -1; } - -static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt) +static void process(struct mp_filter *da) { struct spdifContext *spdif_ctx = da->priv; - if (spdif_ctx->queued_packet || spdif_ctx->got_eof) - return false; + if (!mp_pin_can_transfer_data(da->ppins[1], da->ppins[0])) + return; - spdif_ctx->queued_packet = mpkt ? demux_copy_packet(mpkt) : NULL; - spdif_ctx->got_eof = !mpkt; - return true; -} - -static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) -{ - struct spdifContext *spdif_ctx = da->priv; - - if (spdif_ctx->got_eof) { - spdif_ctx->got_eof = false; - return false; + struct mp_frame inframe = mp_pin_out_read(da->ppins[0]); + if (inframe.type == MP_FRAME_EOF) { + mp_pin_in_write(da->ppins[1], inframe); + return; + } else if (inframe.type != MP_FRAME_PACKET) { + if (inframe.type) { + MP_ERR(da, "unknown frame type\n"); + mp_filter_internal_mark_failed(da); + } + return; } - if (!spdif_ctx->queued_packet) - return true; - - double pts = spdif_ctx->queued_packet->pts; + struct demux_packet *mpkt = inframe.data; + struct mp_aframe *out = NULL; + double pts = mpkt->pts; AVPacket pkt; - mp_set_av_packet(&pkt, spdif_ctx->queued_packet, NULL); + mp_set_av_packet(&pkt, mpkt, NULL); pkt.pts = pkt.dts = 0; if (!spdif_ctx->lavf_ctx) { if (init_filter(da, &pkt) < 0) @@ -316,39 +304,29 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) goto done; } - *out = mp_aframe_new_ref(spdif_ctx->fmt); + out = mp_aframe_new_ref(spdif_ctx->fmt); int samples = spdif_ctx->out_buffer_len / spdif_ctx->sstride; - if (mp_aframe_pool_allocate(spdif_ctx->pool, *out, samples) < 0) { - TA_FREEP(out); + if (mp_aframe_pool_allocate(spdif_ctx->pool, out, samples) < 0) { + TA_FREEP(&out); goto done; } - uint8_t **data = mp_aframe_get_data_rw(*out); + uint8_t **data = mp_aframe_get_data_rw(out); if (!data) { - TA_FREEP(out); + TA_FREEP(&out); goto done; } memcpy(data[0], spdif_ctx->out_buffer, spdif_ctx->out_buffer_len); - mp_aframe_set_pts(*out, pts); + mp_aframe_set_pts(out, pts); done: - talloc_free(spdif_ctx->queued_packet); - spdif_ctx->queued_packet = NULL; - return true; -} - -static int control(struct dec_audio *da, int cmd, void *arg) -{ - struct spdifContext *spdif_ctx = da->priv; - switch (cmd) { - case ADCTRL_RESET: - talloc_free(spdif_ctx->queued_packet); - spdif_ctx->queued_packet = NULL; - spdif_ctx->got_eof = false; - return CONTROL_TRUE; + talloc_free(mpkt); + if (out) { + mp_pin_in_write(da->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, out)); + } else { + mp_filter_internal_mark_failed(da); } - return CONTROL_UNKNOWN; } static const int codecs[] = { @@ -405,12 +383,44 @@ struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref) return list; } -const struct ad_functions ad_spdif = { - .name = "spdif", - .add_decoders = NULL, - .init = init, - .uninit = uninit, - .control = control, - .send_packet = send_packet, - .receive_frame = receive_frame, +static const struct mp_filter_info ad_spdif_filter = { + .name = "ad_spdif", + .priv_size = sizeof(struct spdifContext), + .process = process, + .destroy = destroy, +}; + +static struct mp_decoder *create(struct mp_filter *parent, + struct mp_codec_params *codec, + const char *decoder) +{ + struct mp_filter *da = mp_filter_create(parent, &ad_spdif_filter); + if (!da) + return NULL; + + mp_filter_add_pin(da, MP_PIN_IN, "in"); + mp_filter_add_pin(da, MP_PIN_OUT, "out"); + + da->log = mp_log_new(da, parent->log, NULL); + + struct spdifContext *spdif_ctx = da->priv; + spdif_ctx->log = da->log; + spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx); + spdif_ctx->public.f = da; + + if (strcmp(decoder, "spdif_dts_hd") == 0) + spdif_ctx->use_dts_hd = true; + + spdif_ctx->codec_id = mp_codec_to_av_codec_id(codec->codec); + + + if (spdif_ctx->codec_id == AV_CODEC_ID_NONE) { + talloc_free(da); + return NULL; + } + return &spdif_ctx->public; +} + +const struct mp_decoder_fns ad_spdif = { + .create = create, }; diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c deleted file mode 100644 index 111f981690..0000000000 --- a/audio/decode/dec_audio.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include -#include -#include -#include -#include - -#include - -#include "demux/codec_tags.h" - -#include "common/codecs.h" -#include "common/msg.h" -#include "common/recorder.h" -#include "misc/bstr.h" -#include "options/options.h" - -#include "stream/stream.h" -#include "demux/demux.h" - -#include "demux/stheader.h" - -#include "dec_audio.h" -#include "ad.h" -#include "audio/format.h" - -extern const struct ad_functions ad_lavc; - -// Not a real codec - specially treated. -extern const struct ad_functions ad_spdif; - -static const struct ad_functions * const ad_drivers[] = { - &ad_lavc, - NULL -}; - -static void uninit_decoder(struct dec_audio *d_audio) -{ - audio_reset_decoding(d_audio); - if (d_audio->ad_driver) { - MP_VERBOSE(d_audio, "Uninit audio decoder.\n"); - d_audio->ad_driver->uninit(d_audio); - } - d_audio->ad_driver = NULL; - talloc_free(d_audio->priv); - d_audio->priv = NULL; -} - -static int init_audio_codec(struct dec_audio *d_audio, const char *decoder) -{ - if (!d_audio->ad_driver->init(d_audio, decoder)) { - MP_VERBOSE(d_audio, "Audio decoder init failed.\n"); - d_audio->ad_driver = NULL; - uninit_decoder(d_audio); - return 0; - } - - return 1; -} - -struct mp_decoder_list *audio_decoder_list(void) -{ - struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); - for (int i = 0; ad_drivers[i] != NULL; i++) - ad_drivers[i]->add_decoders(list); - return list; -} - -static struct mp_decoder_list *audio_select_decoders(struct dec_audio *d_audio) -{ - struct MPOpts *opts = d_audio->opts; - const char *codec = d_audio->codec->codec; - - struct mp_decoder_list *list = audio_decoder_list(); - struct mp_decoder_list *new = - mp_select_decoders(d_audio->log, list, codec, opts->audio_decoders); - if (d_audio->try_spdif && codec) { - struct mp_decoder_list *spdif = - select_spdif_codec(codec, opts->audio_spdif); - mp_append_decoders(spdif, new); - talloc_free(new); - new = spdif; - } - talloc_free(list); - return new; -} - -static const struct ad_functions *find_driver(const char *name) -{ - for (int i = 0; ad_drivers[i] != NULL; i++) { - if (strcmp(ad_drivers[i]->name, name) == 0) - return ad_drivers[i]; - } - if (strcmp(name, "spdif") == 0) - return &ad_spdif; - return NULL; -} - -int audio_init_best_codec(struct dec_audio *d_audio) -{ - uninit_decoder(d_audio); - assert(!d_audio->ad_driver); - - struct mp_decoder_entry *decoder = NULL; - struct mp_decoder_list *list = audio_select_decoders(d_audio); - - mp_print_decoders(d_audio->log, MSGL_V, "Codec list:", list); - - for (int n = 0; n < list->num_entries; n++) { - struct mp_decoder_entry *sel = &list->entries[n]; - const struct ad_functions *driver = find_driver(sel->family); - if (!driver) - continue; - MP_VERBOSE(d_audio, "Opening audio decoder %s\n", sel->decoder); - d_audio->ad_driver = driver; - if (init_audio_codec(d_audio, sel->decoder)) { - decoder = sel; - break; - } - MP_WARN(d_audio, "Audio decoder init failed for %s\n", sel->decoder); - } - - if (d_audio->ad_driver) { - d_audio->decoder_desc = - talloc_asprintf(d_audio, "%s (%s)", decoder->decoder, decoder->desc); - MP_VERBOSE(d_audio, "Selected audio codec: %s\n", d_audio->decoder_desc); - } else { - MP_ERR(d_audio, "Failed to initialize an audio decoder for codec '%s'.\n", - d_audio->codec->codec); - } - - talloc_free(list); - return !!d_audio->ad_driver; -} - -void audio_uninit(struct dec_audio *d_audio) -{ - if (!d_audio) - return; - uninit_decoder(d_audio); - talloc_free(d_audio); -} - -void audio_reset_decoding(struct dec_audio *d_audio) -{ - if (d_audio->ad_driver) - d_audio->ad_driver->control(d_audio, ADCTRL_RESET, NULL); - d_audio->pts = MP_NOPTS_VALUE; - talloc_free(d_audio->current_frame); - d_audio->current_frame = NULL; - talloc_free(d_audio->packet); - d_audio->packet = NULL; - talloc_free(d_audio->new_segment); - d_audio->new_segment = NULL; - d_audio->start = d_audio->end = MP_NOPTS_VALUE; -} - -static void fix_audio_pts(struct dec_audio *da) -{ - if (!da->current_frame) - return; - - double frame_pts = mp_aframe_get_pts(da->current_frame); - if (frame_pts != MP_NOPTS_VALUE) { - if (da->pts != MP_NOPTS_VALUE) - MP_STATS(da, "value %f audio-pts-err", da->pts - frame_pts); - - // Keep the interpolated timestamp if it doesn't deviate more - // than 1 ms from the real one. (MKV rounded timestamps.) - if (da->pts == MP_NOPTS_VALUE || fabs(da->pts - frame_pts) > 0.001) - da->pts = frame_pts; - } - - if (da->pts == MP_NOPTS_VALUE && da->header->missing_timestamps) - da->pts = 0; - - mp_aframe_set_pts(da->current_frame, da->pts); - - if (da->pts != MP_NOPTS_VALUE) - da->pts += mp_aframe_duration(da->current_frame); -} - -static bool is_new_segment(struct dec_audio *da, struct demux_packet *p) -{ - return p->segmented && - (p->start != da->start || p->end != da->end || p->codec != da->codec); -} - -static void feed_packet(struct dec_audio *da) -{ - if (da->current_frame || !da->ad_driver) - return; - - if (!da->packet && !da->new_segment && - demux_read_packet_async(da->header, &da->packet) == 0) - { - da->current_state = DATA_WAIT; - return; - } - - if (da->packet && is_new_segment(da, da->packet)) { - assert(!da->new_segment); - da->new_segment = da->packet; - da->packet = NULL; - } - - if (da->ad_driver->send_packet(da, da->packet)) { - if (da->recorder_sink) - mp_recorder_feed_packet(da->recorder_sink, da->packet); - - talloc_free(da->packet); - da->packet = NULL; - } - - da->current_state = DATA_AGAIN; -} - -static void read_frame(struct dec_audio *da) -{ - if (da->current_frame || !da->ad_driver) - return; - - bool progress = da->ad_driver->receive_frame(da, &da->current_frame); - - da->current_state = da->current_frame ? DATA_OK : DATA_AGAIN; - if (!progress) - da->current_state = DATA_EOF; - - fix_audio_pts(da); - - bool segment_end = da->current_state == DATA_EOF; - - if (da->current_frame) { - mp_aframe_clip_timestamps(da->current_frame, da->start, da->end); - double frame_pts = mp_aframe_get_pts(da->current_frame); - if (frame_pts != MP_NOPTS_VALUE && da->start != MP_NOPTS_VALUE) - segment_end = frame_pts >= da->end; - if (mp_aframe_get_size(da->current_frame) == 0) { - talloc_free(da->current_frame); - da->current_frame = NULL; - } - } - - // If there's a new segment, start it as soon as we're drained/finished. - if (segment_end && da->new_segment) { - struct demux_packet *new_segment = da->new_segment; - da->new_segment = NULL; - - if (da->codec == new_segment->codec) { - audio_reset_decoding(da); - } else { - da->codec = new_segment->codec; - da->ad_driver->uninit(da); - da->ad_driver = NULL; - audio_init_best_codec(da); - } - - da->start = new_segment->start; - da->end = new_segment->end; - - da->packet = new_segment; - da->current_state = DATA_AGAIN; - } -} - -void audio_work(struct dec_audio *da) -{ - read_frame(da); - if (!da->current_frame) { - feed_packet(da); - if (da->current_state == DATA_WAIT) - return; - read_frame(da); // retry, to avoid redundant iterations - } -} - -// Fetch an audio frame decoded with audio_work(). Returns one of: -// DATA_OK: *out_frame is set to a new image -// DATA_WAIT: waiting for demuxer; will receive a wakeup signal -// DATA_EOF: end of file, no more frames to be expected -// DATA_AGAIN: dropped frame or something similar -int audio_get_frame(struct dec_audio *da, struct mp_aframe **out_frame) -{ - *out_frame = NULL; - if (da->current_frame) { - *out_frame = da->current_frame; - da->current_frame = NULL; - return DATA_OK; - } - if (da->current_state == DATA_OK) - return DATA_AGAIN; - return da->current_state; -} diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h deleted file mode 100644 index ea504328df..0000000000 --- a/audio/decode/dec_audio.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#ifndef MPLAYER_DEC_AUDIO_H -#define MPLAYER_DEC_AUDIO_H - -#include "audio/chmap.h" -#include "audio/aframe.h" -#include "demux/demux.h" -#include "demux/stheader.h" - -struct mp_decoder_list; - -struct dec_audio { - struct mp_log *log; - struct MPOpts *opts; - struct mpv_global *global; - const struct ad_functions *ad_driver; - struct sh_stream *header; - struct mp_codec_params *codec; - char *decoder_desc; - - bool try_spdif; - - struct mp_recorder_sink *recorder_sink; - - // For free use by the ad_driver - void *priv; - - // Strictly internal (dec_audio.c). - - double pts; // endpts of previous frame - double start, end; - struct demux_packet *packet; - struct demux_packet *new_segment; - struct mp_aframe *current_frame; - int current_state; -}; - -struct mp_decoder_list *audio_decoder_list(void); -int audio_init_best_codec(struct dec_audio *d_audio); -void audio_uninit(struct dec_audio *d_audio); - -void audio_work(struct dec_audio *d_audio); -int audio_get_frame(struct dec_audio *d_audio, struct mp_aframe **out_frame); - -void audio_reset_decoding(struct dec_audio *d_audio); - -// ad_spdif.c -struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref); - -#endif /* MPLAYER_DEC_AUDIO_H */ diff --git a/common/common.h b/common/common.h index 224a6e023a..14a9973371 100644 --- a/common/common.h +++ b/common/common.h @@ -58,14 +58,6 @@ enum stream_type { STREAM_TYPE_COUNT, }; -enum { - DATA_OK = 1, // data is actually being returned - DATA_WAIT = 0, // async wait: check state again after next wakeup - DATA_AGAIN = -2, // repeat request (internal progress was made) - DATA_STARVE = -1, // need input (might require to drain other outputs) - DATA_EOF = -3, // no more data available -}; - extern const char mpv_version[]; extern const char mpv_builddate[]; extern const char mpv_copyright[]; diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c index e85621957f..7e948faebb 100644 --- a/filters/f_decoder_wrapper.c +++ b/filters/f_decoder_wrapper.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,7 @@ #include "common/global.h" #include "common/recorder.h" +#include "audio/aframe.h" #include "video/out/vo.h" #include "video/csputils.h" @@ -149,6 +151,13 @@ struct mp_decoder_list *video_decoder_list(void) return list; } +struct mp_decoder_list *audio_decoder_list(void) +{ + struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); + ad_lavc.add_decoders(list); + return list; +} + bool mp_decoder_wrapper_reinit(struct mp_decoder_wrapper *d) { struct priv *p = d->f->priv; @@ -161,13 +170,36 @@ bool mp_decoder_wrapper_reinit(struct mp_decoder_wrapper *d) reset_decoder(p); p->has_broken_packet_pts = -10; // needs 10 packets to reach decision - const struct mp_decoder_fns *driver = &vd_lavc; + const struct mp_decoder_fns *driver = NULL; + struct mp_decoder_list *list = NULL; + char *user_list = NULL; - struct mp_decoder_list *full = talloc_zero(NULL, struct mp_decoder_list); - driver->add_decoders(full); - struct mp_decoder_list *list = - mp_select_decoders(p->log, full, p->codec->codec, opts->video_decoders); - talloc_free(full); + if (p->codec->type == STREAM_VIDEO) { + driver = &vd_lavc; + user_list = opts->video_decoders; + } else if (p->codec->type == STREAM_AUDIO) { + driver = &ad_lavc; + user_list = opts->audio_decoders; + + if (p->public.try_spdif && p->codec->codec) { + struct mp_decoder_list *spdif = + select_spdif_codec(p->codec->codec, opts->audio_spdif); + if (spdif->num_entries) { + driver = &ad_spdif; + list = spdif; + } else { + talloc_free(spdif); + } + } + } + + if (!list) { + struct mp_decoder_list *full = talloc_zero(NULL, struct mp_decoder_list); + if (driver) + driver->add_decoders(full); + list = mp_select_decoders(p->log, full, p->codec->codec, user_list); + talloc_free(full); + } mp_print_decoders(p->log, MSGL_V, "Codec list:", list); @@ -363,6 +395,29 @@ void mp_decoder_wrapper_get_video_dec_params(struct mp_decoder_wrapper *d, *m = p->dec_format; } +static void process_audio_frame(struct priv *p, struct mp_aframe *aframe) +{ + double frame_pts = mp_aframe_get_pts(aframe); + if (frame_pts != MP_NOPTS_VALUE) { + if (p->pts != MP_NOPTS_VALUE) + MP_STATS(p, "value %f audio-pts-err", p->pts - frame_pts); + + // Keep the interpolated timestamp if it doesn't deviate more + // than 1 ms from the real one. (MKV rounded timestamps.) + if (p->pts == MP_NOPTS_VALUE || fabs(p->pts - frame_pts) > 0.001) + p->pts = frame_pts; + } + + if (p->pts == MP_NOPTS_VALUE && p->header->missing_timestamps) + p->pts = 0; + + mp_aframe_set_pts(aframe, p->pts); + + if (p->pts != MP_NOPTS_VALUE) + p->pts += mp_aframe_duration(aframe); +} + + // Frames before the start timestamp can be dropped. (Used for hr-seek.) void mp_decoder_wrapper_set_start_pts(struct mp_decoder_wrapper *d, double pts) { @@ -470,6 +525,17 @@ static bool process_decoded_frame(struct priv *p, struct mp_frame *frame) if ((p->start != MP_NOPTS_VALUE && vpts < p->start) || segment_ended) mp_frame_unref(frame); } + } else if (frame->type == MP_FRAME_AUDIO) { + struct mp_aframe *aframe = frame->data; + + process_audio_frame(p, aframe); + + mp_aframe_clip_timestamps(aframe, p->start, p->end); + double pts = mp_aframe_get_pts(aframe); + if (pts != MP_NOPTS_VALUE && p->start != MP_NOPTS_VALUE) + segment_ended = pts >= p->end; + if (mp_aframe_get_size(aframe) == 0) + mp_frame_unref(frame); } else { MP_ERR(p, "unknown frame type from decoder\n"); } @@ -588,6 +654,8 @@ struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent, MP_INFO(p, "FPS forced to %5.3f.\n", p->public.fps); MP_INFO(p, "Use --no-correct-pts to force FPS based timing.\n"); } + } else if (p->header->type == STREAM_AUDIO) { + p->log = f->log = mp_log_new(f, parent->log, "!ad"); } struct mp_filter *demux = mp_demux_in_create(f, p->header); diff --git a/filters/f_decoder_wrapper.h b/filters/f_decoder_wrapper.h index 4d970bd79a..e6601052a2 100644 --- a/filters/f_decoder_wrapper.h +++ b/filters/f_decoder_wrapper.h @@ -46,6 +46,11 @@ struct mp_decoder_wrapper { // Framedrop control for playback (not used for hr seek etc.) int attempt_framedrops; // try dropping this many frames int dropped_frames; // total frames _probably_ dropped + + // --- for STREAM_AUDIO + + // Prefer spdif wrapper over real decoders. + bool try_spdif; }; // Create the decoder wrapper for the given stream, plus underlying decoder. @@ -55,6 +60,7 @@ struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent, struct sh_stream *src); struct mp_decoder_list *video_decoder_list(void); +struct mp_decoder_list *audio_decoder_list(void); // For precise seeking: if possible, try to drop frames up until the given PTS. // This is automatically unset if the target is reached, or on reset. @@ -96,9 +102,14 @@ struct mp_decoder_fns { }; extern const struct mp_decoder_fns vd_lavc; +extern const struct mp_decoder_fns ad_lavc; +extern const struct mp_decoder_fns ad_spdif; // Convenience wrapper for lavc based decoders. eof_flag must be set to false // on init and resets. void lavc_process(struct mp_filter *f, bool *eof_flag, bool (*send)(struct mp_filter *f, struct demux_packet *pkt), bool (*receive)(struct mp_filter *f, struct mp_frame *res)); + +// ad_spdif.c +struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref); diff --git a/filters/f_output_chain.c b/filters/f_output_chain.c index e53f9eafaa..ea6a0a3981 100644 --- a/filters/f_output_chain.c +++ b/filters/f_output_chain.c @@ -452,8 +452,13 @@ void mp_output_chain_reset_harder(struct mp_output_chain *c) mp_filter_reset(p->f); p->public.failed_output_conversion = false; - for (int n = 0; n < p->num_all_filters; n++) - p->all_filters[n]->failed = false; + for (int n = 0; n < p->num_all_filters; n++) { + struct mp_user_filter *u = p->all_filters[n]; + + u->failed = false; + u->last_out_params = (struct mp_image_params){0}; + mp_aframe_reset(u->last_out_aformat); + } } static void destroy(struct mp_filter *f) diff --git a/options/options.c b/options/options.c index bce2bf3be6..2f4116299d 100644 --- a/options/options.c +++ b/options/options.c @@ -42,7 +42,6 @@ #include "video/hwdec.h" #include "video/image_writer.h" #include "sub/osd.h" -#include "audio/decode/dec_audio.h" #include "player/core.h" #include "player/command.h" #include "stream/stream.h" 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" diff --git a/wscript_build.py b/wscript_build.py index 1e2b2f7b45..b2d61cf0be 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -180,7 +180,6 @@ def build(ctx): ( "audio/aframe.c" ), ( "audio/decode/ad_lavc.c" ), ( "audio/decode/ad_spdif.c" ), - ( "audio/decode/dec_audio.c" ), ( "audio/filter/af_format.c" ), ( "audio/filter/af_lavcac3enc.c" ), ( "audio/filter/af_lavrresample.c" ),