From 0f5ec05d8f4ae02262dc79a895bce3b465b376f2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 23 Nov 2013 21:22:17 +0100 Subject: audio: move decoder context from sh_audio into new struct Move all state that basically changes during decoding or is needed in order to manage decoding itself into a new struct (dec_audio). sh_audio (defined in stheader.h) is supposed to be the audio stream header. This should reflect the file headers for the stream. Putting the decoder context there is strange design, to say the least. --- audio/decode/ad.h | 11 ++-- audio/decode/ad_lavc.c | 68 ++++++++++---------- audio/decode/ad_mpg123.c | 110 ++++++++++++++++--------------- audio/decode/ad_spdif.c | 30 ++++----- audio/decode/dec_audio.c | 161 +++++++++++++++++++++++++--------------------- audio/decode/dec_audio.h | 30 +++++++-- demux/stheader.h | 5 -- mpvcore/player/audio.c | 85 +++++++++++++----------- mpvcore/player/command.c | 32 ++++----- mpvcore/player/loadfile.c | 30 +++++---- mpvcore/player/main.c | 2 +- mpvcore/player/mp_core.h | 6 +- mpvcore/player/osd.c | 4 +- mpvcore/player/playloop.c | 36 +++++------ mpvcore/player/video.c | 8 +-- 15 files changed, 327 insertions(+), 291 deletions(-) diff --git a/audio/decode/ad.h b/audio/decode/ad.h index 6c76e8dfd0..ed9f4fff75 100644 --- a/audio/decode/ad.h +++ b/audio/decode/ad.h @@ -25,6 +25,7 @@ #include "audio/format.h" #include "audio/audio.h" +#include "dec_audio.h" struct mp_decoder_list; @@ -32,11 +33,11 @@ struct mp_decoder_list; struct ad_functions { const char *name; void (*add_decoders)(struct mp_decoder_list *list); - int (*preinit)(sh_audio_t *sh); - int (*init)(sh_audio_t *sh, const char *decoder); - void (*uninit)(sh_audio_t *sh); - int (*control)(sh_audio_t *sh, int cmd, void *arg); - int (*decode_audio)(sh_audio_t *sh, struct mp_audio *buffer, int maxlen); + int (*preinit)(struct dec_audio *da); + 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); + int (*decode_audio)(struct dec_audio *da, struct mp_audio *buffer, int maxlen); }; enum ad_ctrl { diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 2e0cade8c5..143990414b 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -48,8 +48,8 @@ struct priv { struct demux_packet *packet; }; -static void uninit(sh_audio_t *sh); -static int decode_new_packet(struct sh_audio *sh); +static void uninit(struct dec_audio *da); +static int decode_new_packet(struct dec_audio *da); #define OPT_BASE_STRUCT struct MPOpts @@ -128,15 +128,16 @@ static const char *find_pcm_decoder(const struct pcm_map *map, int format, return NULL; } -static int preinit(sh_audio_t *sh) +static int preinit(struct dec_audio *da) { return 1; } -static int setup_format(sh_audio_t *sh_audio) +static int setup_format(struct dec_audio *da) { - struct priv *priv = sh_audio->context; + struct priv *priv = da->priv; AVCodecContext *lavc_context = priv->avctx; + struct sh_audio *sh_audio = da->header->audio; int sample_format = af_from_avformat(lavc_context->sample_fmt); if (!sample_format) @@ -181,15 +182,16 @@ static void set_from_wf(AVCodecContext *avctx, MP_WAVEFORMATEX *wf) } } -static int init(sh_audio_t *sh_audio, const char *decoder) +static int init(struct dec_audio *da, const char *decoder) { - struct MPOpts *mpopts = sh_audio->opts; + struct MPOpts *mpopts = da->opts; struct ad_lavc_param *opts = &mpopts->ad_lavc_param; AVCodecContext *lavc_context; AVCodec *lavc_codec; + struct sh_audio *sh_audio = da->header->audio; struct priv *ctx = talloc_zero(NULL, struct priv); - sh_audio->context = ctx; + da->priv = ctx; if (sh_audio->wf && strcmp(decoder, "pcm") == 0) { decoder = find_pcm_decoder(tag_map, sh_audio->format, @@ -203,7 +205,7 @@ static int init(sh_audio_t *sh_audio, const char *decoder) if (!lavc_codec) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Cannot find codec '%s' in libavcodec...\n", decoder); - uninit(sh_audio); + uninit(da); return 0; } @@ -227,7 +229,7 @@ static int init(sh_audio_t *sh_audio, const char *decoder) if (parse_avopts(lavc_context, opts->avopt) < 0) { mp_msg(MSGT_DECVIDEO, MSGL_ERR, "ad_lavc: setting AVOptions '%s' failed.\n", opts->avopt); - uninit(sh_audio); + uninit(da); return 0; } } @@ -256,7 +258,7 @@ static int init(sh_audio_t *sh_audio, const char *decoder) /* open it */ if (avcodec_open2(lavc_context, lavc_codec, NULL) < 0) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Could not open codec.\n"); - uninit(sh_audio); + uninit(da); return 0; } mp_msg(MSGT_DECAUDIO, MSGL_V, "INFO: libavcodec \"%s\" init OK!\n", @@ -264,27 +266,27 @@ static int init(sh_audio_t *sh_audio, const char *decoder) // Decode at least 1 sample: (to get header filled) for (int tries = 1; ; tries++) { - int x = decode_new_packet(sh_audio); + int x = decode_new_packet(da); if (x >= 0 && ctx->frame.samples > 0) break; if (tries >= 5) { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "ad_lavc: initial decode failed\n"); - uninit(sh_audio); + uninit(da); return 0; } } - sh_audio->i_bps = lavc_context->bit_rate / 8; + da->i_bps = lavc_context->bit_rate / 8; if (sh_audio->wf && sh_audio->wf->nAvgBytesPerSec) - sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec; + da->i_bps = sh_audio->wf->nAvgBytesPerSec; return 1; } -static void uninit(sh_audio_t *sh) +static void uninit(struct dec_audio *da) { - struct priv *ctx = sh->context; + struct priv *ctx = da->priv; if (!ctx) return; AVCodecContext *lavc_context = ctx->avctx; @@ -296,13 +298,11 @@ static void uninit(sh_audio_t *sh) av_freep(&lavc_context); } avcodec_free_frame(&ctx->avframe); - talloc_free(ctx); - sh->context = NULL; } -static int control(sh_audio_t *sh, int cmd, void *arg) +static int control(struct dec_audio *da, int cmd, void *arg) { - struct priv *ctx = sh->context; + struct priv *ctx = da->priv; switch (cmd) { case ADCTRL_RESYNC_STREAM: avcodec_flush_buffers(ctx->avctx); @@ -314,16 +314,16 @@ static int control(sh_audio_t *sh, int cmd, void *arg) return CONTROL_UNKNOWN; } -static int decode_new_packet(struct sh_audio *sh) +static int decode_new_packet(struct dec_audio *da) { - struct priv *priv = sh->context; + struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; priv->frame.samples = 0; struct demux_packet *mpkt = priv->packet; if (!mpkt) - mpkt = demux_read_packet(sh->gsh); + mpkt = demux_read_packet(da->header); if (!mpkt) return -1; // error or EOF @@ -335,8 +335,8 @@ static int decode_new_packet(struct sh_audio *sh) mp_set_av_packet(&pkt, mpkt); if (mpkt->pts != MP_NOPTS_VALUE) { - sh->pts = mpkt->pts; - sh->pts_offset = 0; + da->pts = mpkt->pts; + da->pts_offset = 0; } int got_frame = 0; int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); @@ -362,13 +362,13 @@ static int decode_new_packet(struct sh_audio *sh) if (!got_frame) return 0; - if (setup_format(sh) < 0) + if (setup_format(da) < 0) return -1; priv->frame.samples = priv->avframe->nb_samples; - mp_audio_set_format(&priv->frame, sh->sample_format); - mp_audio_set_channels(&priv->frame, &sh->channels); - priv->frame.rate = sh->samplerate; + mp_audio_set_format(&priv->frame, da->header->audio->sample_format); + mp_audio_set_channels(&priv->frame, &da->header->audio->channels); + priv->frame.rate = da->header->audio->samplerate; for (int n = 0; n < priv->frame.num_planes; n++) priv->frame.planes[n] = priv->avframe->data[n]; @@ -377,12 +377,12 @@ static int decode_new_packet(struct sh_audio *sh) return 0; } -static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) +static int decode_audio(struct dec_audio *da, struct mp_audio *buffer, int maxlen) { - struct priv *priv = sh->context; + struct priv *priv = da->priv; if (!priv->frame.samples) { - if (decode_new_packet(sh) < 0) + if (decode_new_packet(da) < 0) return -1; } @@ -392,7 +392,7 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) buffer->samples = MPMIN(priv->frame.samples, maxlen); mp_audio_copy(buffer, 0, &priv->frame, 0, buffer->samples); mp_audio_skip_samples(&priv->frame, buffer->samples); - sh->pts_offset += buffer->samples; + da->pts_offset += buffer->samples; return 0; } diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c index 8ea06dd5ab..1abda4e084 100644 --- a/audio/decode/ad_mpg123.c +++ b/audio/decode/ad_mpg123.c @@ -47,20 +47,18 @@ struct ad_mpg123_context { char vbr; }; -static void uninit(sh_audio_t *sh) +static void uninit(struct dec_audio *da) { - struct ad_mpg123_context *con = (struct ad_mpg123_context*) sh->context; + struct ad_mpg123_context *con = da->priv; mpg123_close(con->handle); mpg123_delete(con->handle); - talloc_free(sh->context); - sh->context = NULL; mpg123_exit(); } /* This initializes libmpg123 and prepares the handle, including funky * parameters. */ -static int preinit(sh_audio_t *sh) +static int preinit(struct dec_audio *da) { int err; struct ad_mpg123_context *con; @@ -71,8 +69,8 @@ static int preinit(sh_audio_t *sh) if (mpg123_init() != MPG123_OK) return 0; - sh->context = talloc_zero(NULL, struct ad_mpg123_context); - con = sh->context; + da->priv = talloc_zero(NULL, struct ad_mpg123_context); + con = da->priv; /* Auto-choice of optimized decoder (first argument NULL). */ con->handle = mpg123_new(NULL, &err); if (!con->handle) @@ -123,65 +121,65 @@ static int preinit(sh_audio_t *sh) mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 preinit error: %s\n", mpg123_strerror(con->handle)); - uninit(sh); + uninit(da); + return 0; +} + +static int mpg123_format_to_af(int mpg123_encoding) +{ + /* Without external force, mpg123 will always choose signed encoding, + * and non-16-bit only on builds that don't support it. + * Be reminded that it doesn't matter to the MPEG file what encoding + * is produced from it. */ + switch (mpg123_encoding) { + case MPG123_ENC_SIGNED_8: return AF_FORMAT_S8; + case MPG123_ENC_SIGNED_16: return AF_FORMAT_S16; + case MPG123_ENC_SIGNED_32: return AF_FORMAT_S32; + case MPG123_ENC_FLOAT_32: return AF_FORMAT_FLOAT; + } return 0; } /* libmpg123 has a new format ready; query and store, return return value of mpg123_getformat() */ -static int set_format(sh_audio_t *sh) +static int set_format(struct dec_audio *da) { - struct ad_mpg123_context *con = sh->context; + struct ad_mpg123_context *con = da->priv; int ret; long rate; int channels; int encoding; ret = mpg123_getformat(con->handle, &rate, &channels, &encoding); if (ret == MPG123_OK) { - mp_chmap_from_channels(&sh->channels, channels); - sh->samplerate = rate; - /* Without external force, mpg123 will always choose signed encoding, - * and non-16-bit only on builds that don't support it. - * Be reminded that it doesn't matter to the MPEG file what encoding - * is produced from it. */ - switch (encoding) { - case MPG123_ENC_SIGNED_8: - sh->sample_format = AF_FORMAT_S8; - break; - case MPG123_ENC_SIGNED_16: - sh->sample_format = AF_FORMAT_S16; - break; - case MPG123_ENC_SIGNED_32: - sh->sample_format = AF_FORMAT_S32; - break; - case MPG123_ENC_FLOAT_32: - sh->sample_format = AF_FORMAT_FLOAT; - break; - default: + mp_chmap_from_channels(&da->header->audio->channels, channels); + da->header->audio->samplerate = rate; + int af = mpg123_format_to_af(encoding); + if (!af) { /* This means we got a funny custom build of libmpg123 that only supports an unknown format. */ mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Bad encoding from mpg123: %i.\n", encoding); return MPG123_ERR; } - con->sample_size = channels * (af_fmt2bits(sh->sample_format) / 8); + da->header->audio->sample_format = af; + con->sample_size = channels * (af_fmt2bits(af) / 8); con->new_format = 0; } return ret; } -static int feed_new_packet(sh_audio_t *sh) +static int feed_new_packet(struct dec_audio *da) { - struct ad_mpg123_context *con = sh->context; + struct ad_mpg123_context *con = da->priv; int ret; - struct demux_packet *pkt = demux_read_packet(sh->gsh); + struct demux_packet *pkt = demux_read_packet(da->header); if (!pkt) return -1; /* EOF. */ /* Next bytes from that presentation time. */ if (pkt->pts != MP_NOPTS_VALUE) { - sh->pts = pkt->pts; - sh->pts_offset = 0; + da->pts = pkt->pts; + da->pts_offset = 0; } /* Have to use mpg123_feed() to avoid decoding here. */ @@ -201,9 +199,9 @@ static int feed_new_packet(sh_audio_t *sh) * Format now is allowed to change on-the-fly. Here is the only point * that has MPlayer react to errors. We have to pray that exceptional * erros in other places simply cannot occur. */ -static int init(sh_audio_t *sh, const char *decoder) +static int init(struct dec_audio *da, const char *decoder) { - struct ad_mpg123_context *con = sh->context; + struct ad_mpg123_context *con = da->priv; int ret; ret = mpg123_open_feed(con->handle); @@ -211,14 +209,14 @@ static int init(sh_audio_t *sh, const char *decoder) goto fail; for (int n = 0; ; n++) { - if (feed_new_packet(sh) < 0) { + if (feed_new_packet(da) < 0) { ret = MPG123_NEED_MORE; goto fail; } size_t got_now = 0; ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now); if (ret == MPG123_OK || ret == MPG123_NEW_FORMAT) { - ret = set_format(sh); + ret = set_format(da); if (ret == MPG123_OK) break; } @@ -241,7 +239,7 @@ fail: mpg123_strerror(con->handle)); } - uninit(sh); + uninit(da); return 0; } @@ -260,9 +258,9 @@ static int compute_bitrate(struct mpg123_frameinfo *i) /* Update mean bitrate. This could be dropped if accurate time display * on audio file playback is not desired. */ -static void update_info(sh_audio_t *sh) +static void update_info(struct dec_audio *da) { - struct ad_mpg123_context *con = sh->context; + struct ad_mpg123_context *con = da->priv; struct mpg123_frameinfo finfo; if (mpg123_info(con->handle, &finfo) != MPG123_OK) return; @@ -275,12 +273,12 @@ static void update_info(sh_audio_t *sh) /* Might not be numerically optimal, but works fine enough. */ con->mean_rate = ((con->mean_count - 1) * con->mean_rate + finfo.bitrate) / con->mean_count; - sh->i_bps = (int) (con->mean_rate * 1000 / 8); + da->i_bps = (int) (con->mean_rate * 1000 / 8); con->delay = 10; } } else { - sh->i_bps = (finfo.bitrate ? finfo.bitrate : compute_bitrate(&finfo)) + da->i_bps = (finfo.bitrate ? finfo.bitrate : compute_bitrate(&finfo)) * 1000 / 8; con->delay = 1; con->mean_rate = 0.; @@ -288,14 +286,14 @@ static void update_info(sh_audio_t *sh) } } -static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) +static int decode_audio(struct dec_audio *da, struct mp_audio *buffer, int maxlen) { - struct ad_mpg123_context *con = sh->context; + struct ad_mpg123_context *con = da->priv; void *buf = buffer->planes[0]; int ret; if (con->new_format) { - ret = set_format(sh); + ret = set_format(da); if (ret == MPG123_OK) { return 0; // let caller handle format change } else if (ret == MPG123_NEED_MORE) { @@ -306,13 +304,13 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) } if (con->need_data) { - if (feed_new_packet(sh) < 0) + if (feed_new_packet(da) < 0) return -1; } - if (sh->samplerate != buffer->rate || - !mp_chmap_equals(&sh->channels, &buffer->channels) || - sh->sample_format != buffer->format) + if (da->header->audio->samplerate != buffer->rate || + !mp_chmap_equals(&da->header->audio->channels, &buffer->channels) || + da->header->audio->sample_format != buffer->format) return 0; size_t got_now = 0; @@ -324,7 +322,7 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) int got_samples = got_now / con->sample_size; buffer->samples += got_samples; - sh->pts_offset += got_samples; + da->pts_offset += got_samples; if (ret == MPG123_NEW_FORMAT) { con->new_format = true; @@ -334,7 +332,7 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) goto mpg123_fail; } - update_info(sh); + update_info(da); return 0; mpg123_fail: @@ -343,9 +341,9 @@ mpg123_fail: return -1; } -static int control(sh_audio_t *sh, int cmd, void *arg) +static int control(struct dec_audio *da, int cmd, void *arg) { - struct ad_mpg123_context *con = sh->context; + struct ad_mpg123_context *con = da->priv; switch (cmd) { case ADCTRL_RESYNC_STREAM: diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index e6e94489a6..2630cc89b9 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -57,9 +57,9 @@ static int write_packet(void *p, uint8_t *buf, int buf_size) return buf_size; } -static void uninit(sh_audio_t *sh) +static void uninit(struct dec_audio *da) { - struct spdifContext *spdif_ctx = sh->context; + struct spdifContext *spdif_ctx = da->priv; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; if (lavf_ctx) { @@ -70,18 +70,17 @@ static void uninit(sh_audio_t *sh) av_freep(&lavf_ctx->pb); avformat_free_context(lavf_ctx); } - talloc_free(spdif_ctx); } -static int preinit(sh_audio_t *sh) +static int preinit(struct dec_audio *da) { return 1; } -static int init(sh_audio_t *sh, const char *decoder) +static int init(struct dec_audio *da, const char *decoder) { struct spdifContext *spdif_ctx = talloc_zero(NULL, struct spdifContext); - sh->context = spdif_ctx; + da->priv = spdif_ctx; AVFormatContext *lavf_ctx = avformat_alloc_context(); if (!lavf_ctx) @@ -117,6 +116,7 @@ static int init(sh_audio_t *sh, const char *decoder) AVDictionary *format_opts = NULL; int num_channels = 0; + struct sh_audio *sh = da->header->audio; switch (stream->codec->codec_id) { case AV_CODEC_ID_AAC: spdif_ctx->iec61937_packet_size = 16384; @@ -181,16 +181,16 @@ static int init(sh_audio_t *sh, const char *decoder) return 1; fail: - uninit(sh); + uninit(da); return 0; } -static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) +static int decode_audio(struct dec_audio *da, struct mp_audio *buffer, int maxlen) { - struct spdifContext *spdif_ctx = sh->context; + struct spdifContext *spdif_ctx = da->priv; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; - int sstride = 2 * sh->channels.num; + int sstride = 2 * da->header->audio->channels.num; assert(sstride == buffer->sstride); if (maxlen * sstride < spdif_ctx->iec61937_packet_size) @@ -200,7 +200,7 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) spdif_ctx->out_buffer_size = maxlen * sstride; spdif_ctx->out_buffer = buffer->planes[0]; - struct demux_packet *mpkt = demux_read_packet(sh->gsh); + struct demux_packet *mpkt = demux_read_packet(da->header); if (!mpkt) return -1; @@ -209,13 +209,13 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) pkt.pts = pkt.dts = 0; mp_msg(MSGT_DECAUDIO, MSGL_V, "spdif packet, size=%d\n", pkt.size); if (mpkt->pts != MP_NOPTS_VALUE) { - sh->pts = mpkt->pts; - sh->pts_offset = 0; + da->pts = mpkt->pts; + da->pts_offset = 0; } int ret = av_write_frame(lavf_ctx, &pkt); avio_flush(lavf_ctx->pb); buffer->samples = spdif_ctx->out_buffer_len / sstride; - sh->pts_offset += buffer->samples; + da->pts_offset += buffer->samples; talloc_free(mpkt); if (ret < 0) return -1; @@ -223,7 +223,7 @@ static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen) return 0; } -static int control(sh_audio_t *sh, int cmd, void *arg) +static int control(struct dec_audio *da, int cmd, void *arg) { return CONTROL_UNKNOWN; } diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index e2200918ef..39ee3d5695 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -64,46 +64,59 @@ static const struct ad_functions * const ad_drivers[] = { #define DECODE_BUFFER_SAMPLES (8192 + DECODE_MAX_UNIT) // Drop audio buffer and reinit it (after format change) -static void reinit_audio_buffer(sh_audio_t *sh) +static void reinit_audio_buffer(struct dec_audio *da) { - mp_audio_buffer_reinit_fmt(sh->decode_buffer, sh->sample_format, + struct sh_audio *sh = da->header->audio; + mp_audio_buffer_reinit_fmt(da->decode_buffer, sh->sample_format, &sh->channels, sh->samplerate); - mp_audio_buffer_preallocate_min(sh->decode_buffer, DECODE_BUFFER_SAMPLES); + mp_audio_buffer_preallocate_min(da->decode_buffer, DECODE_BUFFER_SAMPLES); } -static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) +static void uninit_decoder(struct dec_audio *d_audio) { - assert(!sh_audio->initialized); - resync_audio_stream(sh_audio); - if (!sh_audio->ad_driver->preinit(sh_audio)) { + if (d_audio->initialized) { + mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio decoder.\n"); + d_audio->ad_driver->uninit(d_audio); + d_audio->initialized = 0; + } + talloc_free(d_audio->priv); + d_audio->priv = NULL; +} + +static int init_audio_codec(struct dec_audio *d_audio, const char *decoder) +{ + assert(!d_audio->initialized); + audio_resync_stream(d_audio); + if (!d_audio->ad_driver->preinit(d_audio)) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder preinit failed.\n"); return 0; } - if (!sh_audio->ad_driver->init(sh_audio, decoder)) { + if (!d_audio->ad_driver->init(d_audio, decoder)) { mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Audio decoder init failed.\n"); - uninit_audio(sh_audio); // free buffers + uninit_decoder(d_audio); return 0; } - sh_audio->initialized = 1; + d_audio->initialized = 1; - if (mp_chmap_is_empty(&sh_audio->channels) || !sh_audio->samplerate || - !sh_audio->sample_format) + struct sh_audio *sh = d_audio->header->audio; + if (mp_chmap_is_empty(&sh->channels) || !sh->samplerate || + !sh->sample_format) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder did not specify " "audio format!\n"); - uninit_audio(sh_audio); // free buffers + uninit_decoder(d_audio); return 0; } - sh_audio->decode_buffer = mp_audio_buffer_create(NULL); - reinit_audio_buffer(sh_audio); + d_audio->decode_buffer = mp_audio_buffer_create(NULL); + reinit_audio_buffer(d_audio); return 1; } -struct mp_decoder_list *mp_audio_decoder_list(void) +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++) @@ -111,10 +124,10 @@ struct mp_decoder_list *mp_audio_decoder_list(void) return list; } -static struct mp_decoder_list *mp_select_audio_decoders(const char *codec, - char *selection) +static struct mp_decoder_list *audio_select_decoders(const char *codec, + char *selection) { - struct mp_decoder_list *list = mp_audio_decoder_list(); + struct mp_decoder_list *list = audio_decoder_list(); struct mp_decoder_list *new = mp_select_decoders(list, codec, selection); talloc_free(list); return new; @@ -129,13 +142,13 @@ static const struct ad_functions *find_driver(const char *name) return NULL; } -int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) +int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders) { - assert(!sh_audio->initialized); + assert(!d_audio->initialized); struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = - mp_select_audio_decoders(sh_audio->gsh->codec, audio_decoders); + audio_select_decoders(d_audio->header->codec, audio_decoders); mp_print_decoders(MSGT_DECAUDIO, MSGL_V, "Codec list:", list); @@ -146,68 +159,65 @@ int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) continue; mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder %s:%s\n", sel->family, sel->decoder); - sh_audio->ad_driver = driver; - if (init_audio_codec(sh_audio, sel->decoder)) { + d_audio->ad_driver = driver; + if (init_audio_codec(d_audio, sel->decoder)) { decoder = sel; break; } - sh_audio->ad_driver = NULL; + d_audio->ad_driver = NULL; mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } - if (sh_audio->initialized) { - sh_audio->gsh->decoder_desc = - talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family, + if (d_audio->initialized) { + d_audio->decoder_desc = + talloc_asprintf(d_audio, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n", - sh_audio->gsh->decoder_desc); + d_audio->decoder_desc); mp_msg(MSGT_DECAUDIO, MSGL_V, "AUDIO: %d Hz, %d ch, %s\n", - sh_audio->samplerate, sh_audio->channels.num, - af_fmt_to_str(sh_audio->sample_format)); + d_audio->header->audio->samplerate, d_audio->header->audio->channels.num, + af_fmt_to_str(d_audio->header->audio->sample_format)); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", - sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num); + d_audio->i_bps * 8, d_audio->header->audio->samplerate, + d_audio->header->audio->channels.num); } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Failed to initialize an audio decoder for codec '%s'.\n", - sh_audio->gsh->codec ? sh_audio->gsh->codec : ""); + d_audio->header->codec ? d_audio->header->codec : ""); } talloc_free(list); - return sh_audio->initialized; + return d_audio->initialized; } -void uninit_audio(sh_audio_t *sh_audio) +void audio_uninit(struct dec_audio *d_audio) { - if (sh_audio->afilter) { + if (!d_audio) + return; + if (d_audio->afilter) { mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio filters...\n"); - af_destroy(sh_audio->afilter); - sh_audio->afilter = NULL; - } - if (sh_audio->initialized) { - mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio.\n"); - sh_audio->ad_driver->uninit(sh_audio); - sh_audio->initialized = 0; + af_destroy(d_audio->afilter); + d_audio->afilter = NULL; } - talloc_free(sh_audio->gsh->decoder_desc); - sh_audio->gsh->decoder_desc = NULL; - talloc_free(sh_audio->decode_buffer); - sh_audio->decode_buffer = NULL; + uninit_decoder(d_audio); + talloc_free(d_audio->decode_buffer); + talloc_free(d_audio); } -int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, +int audio_init_filters(struct dec_audio *d_audio, int in_samplerate, int *out_samplerate, struct mp_chmap *out_channels, int *out_format) { - if (!sh_audio->afilter) - sh_audio->afilter = af_new(sh_audio->opts); - struct af_stream *afs = sh_audio->afilter; + if (!d_audio->afilter) + d_audio->afilter = af_new(d_audio->opts); + struct af_stream *afs = d_audio->afilter; // input format: same as codec's output format: - mp_audio_buffer_get_format(sh_audio->decode_buffer, &afs->input); + mp_audio_buffer_get_format(d_audio->decode_buffer, &afs->input); // Sample rate can be different when adjusting playback speed afs->input.rate = in_samplerate; @@ -226,7 +236,7 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, // let's autoprobe it! if (af_init(afs) != 0) { af_destroy(afs); - sh_audio->afilter = NULL; + d_audio->afilter = NULL; return 0; // failed :( } @@ -238,34 +248,35 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, } // Filter len bytes of input, put result into outbuf. -static int filter_n_bytes(sh_audio_t *sh, struct mp_audio_buffer *outbuf, +static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf, int len) { int error = 0; struct mp_audio config; - mp_audio_buffer_get_format(sh->decode_buffer, &config); + mp_audio_buffer_get_format(da->decode_buffer, &config); - while (mp_audio_buffer_samples(sh->decode_buffer) < len) { - int maxlen = mp_audio_buffer_get_write_available(sh->decode_buffer); + while (mp_audio_buffer_samples(da->decode_buffer) < len) { + int maxlen = mp_audio_buffer_get_write_available(da->decode_buffer); if (maxlen < DECODE_MAX_UNIT) break; struct mp_audio buffer; - mp_audio_buffer_get_write_buffer(sh->decode_buffer, maxlen, &buffer); + mp_audio_buffer_get_write_buffer(da->decode_buffer, maxlen, &buffer); buffer.samples = 0; - error = sh->ad_driver->decode_audio(sh, &buffer, maxlen); + error = da->ad_driver->decode_audio(da, &buffer, maxlen); if (error < 0) break; // Commit the data just read as valid data - mp_audio_buffer_finish_write(sh->decode_buffer, buffer.samples); + mp_audio_buffer_finish_write(da->decode_buffer, buffer.samples); // Format change + struct sh_audio *sh = da->header->audio; if (sh->samplerate != config.rate || !mp_chmap_equals(&sh->channels, &config.channels) || sh->sample_format != config.format) { // If there are still samples left in the buffer, let them drain // first, and don't signal a format change to the caller yet. - if (mp_audio_buffer_samples(sh->decode_buffer) > 0) + if (mp_audio_buffer_samples(da->decode_buffer) > 0) break; error = -2; break; @@ -274,33 +285,33 @@ static int filter_n_bytes(sh_audio_t *sh, struct mp_audio_buffer *outbuf, // Filter struct mp_audio filter_input; - mp_audio_buffer_peek(sh->decode_buffer, &filter_input); - filter_input.rate = sh->afilter->input.rate; // due to playback speed change + mp_audio_buffer_peek(da->decode_buffer, &filter_input); + filter_input.rate = da->afilter->input.rate; // due to playback speed change len = MPMIN(filter_input.samples, len); filter_input.samples = len; - struct mp_audio *filter_output = af_play(sh->afilter, &filter_input); + struct mp_audio *filter_output = af_play(da->afilter, &filter_input); if (!filter_output) return -1; mp_audio_buffer_append(outbuf, filter_output); // remove processed data from decoder buffer: - mp_audio_buffer_skip(sh->decode_buffer, len); + mp_audio_buffer_skip(da->decode_buffer, len); // Assume the filter chain is drained from old data at this point. // (If not, the remaining old data is discarded.) if (error == -2) - reinit_audio_buffer(sh); + reinit_audio_buffer(da); return error; } /* Try to get at least minsamples decoded+filtered samples in outbuf * (total length including possible existing data). - * Return 0 on success, -1 on error/EOF (not distinguished). + * Return 0 on success, -1 on error/EOF (not distinguidaed). * In the former case outbuf has at least minsamples buffered on return. * In case of EOF/error it might or might not be. */ -int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, +int audio_decode(struct dec_audio *d_audio, struct mp_audio_buffer *outbuf, int minsamples) { // Indicates that a filter seems to be buffering large amounts of data @@ -312,7 +323,7 @@ int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, /* Filter output size will be about filter_multiplier times input size. * If some filter buffers audio in big blocks this might only hold * as average over time. */ - double filter_multiplier = af_calc_filter_multiplier(sh_audio->afilter); + double filter_multiplier = af_calc_filter_multiplier(d_audio->afilter); int prev_buffered = -1; while (minsamples >= 0) { @@ -341,18 +352,18 @@ int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, * of buffering in filters */ huge_filter_buffer = 1; - int res = filter_n_bytes(sh_audio, outbuf, decsamples); + int res = filter_n_bytes(d_audio, outbuf, decsamples); if (res < 0) return res; } return 0; } -void resync_audio_stream(sh_audio_t *sh_audio) +void audio_resync_stream(struct dec_audio *d_audio) { - sh_audio->pts = MP_NOPTS_VALUE; - sh_audio->pts_offset = 0; - if (!sh_audio->initialized) + d_audio->pts = MP_NOPTS_VALUE; + d_audio->pts_offset = 0; + if (!d_audio->initialized) return; - sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); + d_audio->ad_driver->control(d_audio, ADCTRL_RESYNC_STREAM, NULL); } diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h index 3ec5954471..bc5c3793d8 100644 --- a/audio/decode/dec_audio.h +++ b/audio/decode/dec_audio.h @@ -25,14 +25,32 @@ struct mp_audio_buffer; struct mp_decoder_list; -struct mp_decoder_list *mp_audio_decoder_list(void); -int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders); -int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, +struct dec_audio { + struct MPOpts *opts; + const struct ad_functions *ad_driver; + struct sh_stream *header; + struct mp_audio_buffer *decode_buffer; + struct af_stream *afilter; + int initialized; + char *decoder_desc; + // set by decoder + int i_bps; // input bitrate + // last known pts value in output from decoder + double pts; + // number of samples output by decoder after last known pts + int pts_offset; + // For free use by the decoder + void *priv; +}; + +struct mp_decoder_list *audio_decoder_list(void); +int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders); +int audio_decode(struct dec_audio *d_audio, struct mp_audio_buffer *outbuf, int minsamples); -void resync_audio_stream(sh_audio_t *sh_audio); -void uninit_audio(sh_audio_t *sh_audio); +void audio_resync_stream(struct dec_audio *d_audio); +void audio_uninit(struct dec_audio *d_audio); -int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, +int audio_init_filters(struct dec_audio *d_audio, int in_samplerate, int *out_samplerate, struct mp_chmap *out_channels, int *out_format); diff --git a/demux/stheader.h b/demux/stheader.h index c88ed0b0f7..ab190cca83 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -92,16 +92,11 @@ typedef struct sh_audio { int samplerate; struct mp_chmap channels; int i_bps; // == bitrate (compressed bytes/sec) - // decoder state: - struct mp_audio_buffer *decode_buffer; - struct af_stream *afilter; // the audio filter stream - const struct ad_functions *ad_driver; // win32-compatible codec parameters: MP_WAVEFORMATEX *wf; // note codec extradata may be either under "wf" or "codecdata" unsigned char *codecdata; int codecdata_len; - int pts_offset; // number of samples output by decoder after last known pts } sh_audio_t; typedef struct sh_video { diff --git a/mpvcore/player/audio.c b/mpvcore/player/audio.c index 3bf338c21d..ce161a58d5 100644 --- a/mpvcore/player/audio.c +++ b/mpvcore/player/audio.c @@ -41,18 +41,18 @@ static int build_afilter_chain(struct MPContext *mpctx) { - struct sh_audio *sh_audio = mpctx->sh_audio; + struct dec_audio *d_audio = mpctx->d_audio; struct ao *ao = mpctx->ao; struct MPOpts *opts = mpctx->opts; - if (!sh_audio->initialized) + if (!d_audio) return 0; struct mp_audio in_format; - mp_audio_buffer_get_format(mpctx->sh_audio->decode_buffer, &in_format); + mp_audio_buffer_get_format(d_audio->decode_buffer, &in_format); int new_srate; - if (af_control_any_rev(sh_audio->afilter, AF_CONTROL_SET_PLAYBACK_SPEED, + if (af_control_any_rev(d_audio->afilter, AF_CONTROL_SET_PLAYBACK_SPEED, &opts->playback_speed)) new_srate = in_format.rate; else { @@ -66,13 +66,13 @@ static int build_afilter_chain(struct MPContext *mpctx) opts->playback_speed = new_srate / (double)in_format.rate; } } - return init_audio_filters(sh_audio, new_srate, + return audio_init_filters(d_audio, new_srate, &ao->samplerate, &ao->channels, &ao->format); } static int recreate_audio_filters(struct MPContext *mpctx) { - assert(mpctx->sh_audio); + assert(mpctx->d_audio); // init audio filters: if (!build_afilter_chain(mpctx)) { @@ -80,19 +80,19 @@ static int recreate_audio_filters(struct MPContext *mpctx) return -1; } - mixer_reinit_audio(mpctx->mixer, mpctx->ao, mpctx->sh_audio->afilter); + mixer_reinit_audio(mpctx->mixer, mpctx->ao, mpctx->d_audio->afilter); return 0; } int reinit_audio_filters(struct MPContext *mpctx) { - struct sh_audio *sh_audio = mpctx->sh_audio; - if (!sh_audio) + struct dec_audio *d_audio = mpctx->d_audio; + if (!d_audio) return -2; - af_uninit(mpctx->sh_audio->afilter); - if (af_init(mpctx->sh_audio->afilter) < 0) + af_uninit(mpctx->d_audio->afilter); + if (af_init(mpctx->d_audio->afilter) < 0) return -1; if (recreate_audio_filters(mpctx) < 0) return -1; @@ -103,20 +103,25 @@ int reinit_audio_filters(struct MPContext *mpctx) void reinit_audio_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - init_demux_stream(mpctx, STREAM_AUDIO); - if (!mpctx->sh_audio) { + struct sh_stream *sh = init_demux_stream(mpctx, STREAM_AUDIO); + if (!sh) { uninit_player(mpctx, INITIALIZED_AO); goto no_audio; } if (!(mpctx->initialized_flags & INITIALIZED_ACODEC)) { - if (!init_best_audio_codec(mpctx->sh_audio, opts->audio_decoders)) - goto init_error; mpctx->initialized_flags |= INITIALIZED_ACODEC; + assert(!mpctx->d_audio); + mpctx->d_audio = talloc_zero(NULL, struct dec_audio); + mpctx->d_audio->opts = opts; + mpctx->d_audio->header = sh; + if (!audio_init_best_codec(mpctx->d_audio, opts->audio_decoders)) + goto init_error; } + assert(mpctx->d_audio); struct mp_audio in_format; - mp_audio_buffer_get_format(mpctx->sh_audio->decode_buffer, &in_format); + mp_audio_buffer_get_format(mpctx->d_audio->decode_buffer, &in_format); int ao_srate = opts->force_srate; int ao_format = opts->audio_output_format; @@ -137,7 +142,7 @@ void reinit_audio_chain(struct MPContext *mpctx) // Determine what the filter chain outputs. build_afilter_chain() also // needs this for testing whether playback speed is changed by resampling // or using a special filter. - if (!init_audio_filters(mpctx->sh_audio, // preliminary init + if (!audio_init_filters(mpctx->d_audio, // preliminary init // input: in_format.rate, // output: @@ -188,31 +193,31 @@ no_audio: // ao so far. double written_audio_pts(struct MPContext *mpctx) { - sh_audio_t *sh_audio = mpctx->sh_audio; - if (!sh_audio || !sh_audio->initialized) + struct dec_audio *d_audio = mpctx->d_audio; + if (!d_audio) return MP_NOPTS_VALUE; struct mp_audio in_format; - mp_audio_buffer_get_format(mpctx->sh_audio->decode_buffer, &in_format); + mp_audio_buffer_get_format(d_audio->decode_buffer, &in_format); // first calculate the end pts of audio that has been output by decoder - double a_pts = sh_audio->pts; + double a_pts = d_audio->pts; if (a_pts == MP_NOPTS_VALUE) return MP_NOPTS_VALUE; - // sh_audio->pts is the timestamp of the latest input packet with - // known pts that the decoder has decoded. sh_audio->pts_bytes is + // d_audio->pts is the timestamp of the latest input packet with + // known pts that the decoder has decoded. d_audio->pts_bytes is // the amount of bytes the decoder has written after that timestamp. - a_pts += sh_audio->pts_offset / (double)in_format.rate; + a_pts += d_audio->pts_offset / (double)in_format.rate; // Now a_pts hopefully holds the pts for end of audio from decoder. // Subtract data in buffers between decoder and audio out. // Decoded but not filtered - a_pts -= mp_audio_buffer_seconds(sh_audio->decode_buffer); + a_pts -= mp_audio_buffer_seconds(d_audio->decode_buffer); // Data buffered in audio filters, measured in seconds of "missing" output - double buffered_output = af_calc_delay(sh_audio->afilter); + double buffered_output = af_calc_delay(d_audio->afilter); // Data that was ready for ao but was buffered because ao didn't fully // accept everything to internal buffers yet @@ -275,11 +280,13 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) { struct ao *ao = mpctx->ao; struct MPOpts *opts = mpctx->opts; - sh_audio_t * const sh_audio = mpctx->sh_audio; + struct dec_audio *d_audio = mpctx->d_audio; int res; + assert(d_audio); + // Timing info may not be set without - res = decode_audio(sh_audio, ao->buffer, 1); + res = audio_decode(d_audio, ao->buffer, 1); if (res < 0) return res; @@ -300,10 +307,10 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) samples = ptsdiff * real_samplerate; // ogg demuxers give packets without timing - if (written_pts <= 1 && sh_audio->pts == MP_NOPTS_VALUE) { + if (written_pts <= 1 && d_audio->pts == MP_NOPTS_VALUE) { if (!did_retry) { // Try to read more data to see packets that have pts - res = decode_audio(sh_audio, ao->buffer, ao->samplerate); + res = audio_decode(d_audio, ao->buffer, ao->samplerate); if (res < 0) return res; did_retry = true; @@ -321,12 +328,12 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) mpctx->syncing_audio = false; int skip_samples = -samples; int a = MPMIN(skip_samples, MPMAX(playsize, 2500)); - res = decode_audio(sh_audio, ao->buffer, a); + res = audio_decode(d_audio, ao->buffer, a); if (skip_samples <= mp_audio_buffer_samples(ao->buffer)) { mp_audio_buffer_skip(ao->buffer, skip_samples); if (res < 0) return res; - return decode_audio(sh_audio, ao->buffer, playsize); + return audio_decode(d_audio, ao->buffer, playsize); } mp_audio_buffer_clear(ao->buffer); if (res < 0) @@ -346,7 +353,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) } mpctx->syncing_audio = false; mp_audio_buffer_prepend_silence(ao->buffer, samples); - return decode_audio(sh_audio, ao->buffer, playsize); + return audio_decode(d_audio, ao->buffer, playsize); } int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) @@ -358,9 +365,11 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) bool audio_eof = false; bool signal_eof = false; bool partial_fill = false; - sh_audio_t * const sh_audio = mpctx->sh_audio; + struct dec_audio *d_audio = mpctx->d_audio; bool modifiable_audio_format = !(ao->format & AF_FORMAT_SPECIAL_MASK); + assert(d_audio); + if (mpctx->paused) playsize = 1; // just initialize things (audio pts at least) else @@ -378,7 +387,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) if (mpctx->syncing_audio || mpctx->hrseek_active) res = audio_start_sync(mpctx, playsize); else - res = decode_audio(sh_audio, ao->buffer, playsize); + res = audio_decode(d_audio, ao->buffer, playsize); if (res < 0) { // EOF, error or format change if (res == -2) { @@ -392,7 +401,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) return -1; } else if (res == ASYNC_PLAY_DONE) return 0; - else if (demux_stream_eof(mpctx->sh_audio->gsh)) + else if (demux_stream_eof(d_audio->header)) audio_eof = true; } @@ -455,6 +464,6 @@ void clear_audio_output_buffers(struct MPContext *mpctx) // Drop decoded data queued for filtering. void clear_audio_decode_buffers(struct MPContext *mpctx) { - if (mpctx->sh_audio && mpctx->sh_audio->decode_buffer) - mp_audio_buffer_clear(mpctx->sh_audio->decode_buffer); + if (mpctx->d_audio) + mp_audio_buffer_clear(mpctx->d_audio->decode_buffer); } diff --git a/mpvcore/player/command.c b/mpvcore/player/command.c index be34d4e8f5..dc190adfc6 100644 --- a/mpvcore/player/command.c +++ b/mpvcore/player/command.c @@ -123,7 +123,7 @@ static int mp_property_playback_speed(m_option_t *prop, int action, opts->playback_speed = *(double *) arg; // Adjust time until next frame flip for nosound mode mpctx->time_frame *= orig_speed / opts->playback_speed; - if (mpctx->sh_audio) + if (mpctx->d_audio) reinit_audio_chain(mpctx); return M_PROPERTY_OK; } @@ -315,7 +315,7 @@ static int mp_property_length(m_option_t *prop, int action, void *arg, static int mp_property_avsync(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - if (!mpctx->sh_audio || !mpctx->sh_video) + if (!mpctx->d_audio || !mpctx->sh_video) return M_PROPERTY_UNAVAILABLE; if (mpctx->last_av_difference == MP_NOPTS_VALUE) return M_PROPERTY_UNAVAILABLE; @@ -625,8 +625,8 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, if (mpctx->sh_video) resync_video_stream(mpctx->sh_video); - if (mpctx->sh_audio) - resync_audio_stream(mpctx->sh_audio); + if (mpctx->d_audio) + audio_resync_stream(mpctx->d_audio); } return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: { @@ -816,7 +816,7 @@ static int mp_property_volrestore(m_option_t *prop, int action, static int mp_property_audio_delay(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - if (!(mpctx->sh_audio && mpctx->sh_video)) + if (!(mpctx->d_audio && mpctx->sh_video)) return M_PROPERTY_UNAVAILABLE; float delay = mpctx->opts->audio_delay; switch (action) { @@ -835,7 +835,7 @@ static int mp_property_audio_delay(m_option_t *prop, int action, static int mp_property_audio_format(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - const char *c = mpctx->sh_audio ? mpctx->sh_audio->gsh->codec : NULL; + const char *c = mpctx->d_audio ? mpctx->d_audio->header->codec : NULL; return m_property_strdup_ro(prop, action, arg, c); } @@ -843,7 +843,7 @@ static int mp_property_audio_format(m_option_t *prop, int action, static int mp_property_audio_codec(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - const char *c = mpctx->sh_audio ? mpctx->sh_audio->gsh->decoder_desc : NULL; + const char *c = mpctx->d_audio ? mpctx->d_audio->decoder_desc : NULL; return m_property_strdup_ro(prop, action, arg, c); } @@ -851,14 +851,14 @@ static int mp_property_audio_codec(m_option_t *prop, int action, static int mp_property_audio_bitrate(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - if (!mpctx->sh_audio) + if (!mpctx->d_audio) return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_PRINT: - *(char **)arg = format_bitrate(mpctx->sh_audio->i_bps); + *(char **)arg = format_bitrate(mpctx->d_audio->i_bps); return M_PROPERTY_OK; case M_PROPERTY_GET: - *(int *)arg = mpctx->sh_audio->i_bps; + *(int *)arg = mpctx->d_audio->i_bps; return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -868,15 +868,15 @@ static int mp_property_audio_bitrate(m_option_t *prop, int action, static int mp_property_samplerate(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - if (!mpctx->sh_audio) + if (!mpctx->d_audio) return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_PRINT: *(char **)arg = talloc_asprintf(NULL, "%d kHz", - mpctx->sh_audio->samplerate / 1000); + mpctx->d_audio->header->audio->samplerate / 1000); return M_PROPERTY_OK; case M_PROPERTY_GET: - *(int *)arg = mpctx->sh_audio->samplerate; + *(int *)arg = mpctx->d_audio->header->audio->samplerate; return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -886,14 +886,14 @@ static int mp_property_samplerate(m_option_t *prop, int action, void *arg, static int mp_property_channels(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - if (!mpctx->sh_audio) + if (!mpctx->d_audio) return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_PRINT: - *(char **) arg = mp_chmap_to_str(&mpctx->sh_audio->channels); + *(char **) arg = mp_chmap_to_str(&mpctx->d_audio->header->audio->channels); return M_PROPERTY_OK; case M_PROPERTY_GET: - *(int *)arg = mpctx->sh_audio->channels.num; + *(int *)arg = mpctx->d_audio->header->audio->channels.num; return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; diff --git a/mpvcore/player/loadfile.c b/mpvcore/player/loadfile.c index f6e7f6c117..44887ae107 100644 --- a/mpvcore/player/loadfile.c +++ b/mpvcore/player/loadfile.c @@ -73,8 +73,8 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) if (mask & INITIALIZED_ACODEC) { mpctx->initialized_flags &= ~INITIALIZED_ACODEC; mixer_uninit_audio(mpctx->mixer); - if (mpctx->sh_audio) - uninit_audio(mpctx->sh_audio); + audio_uninit(mpctx->d_audio); + mpctx->d_audio = NULL; cleanup_demux_stream(mpctx, STREAM_AUDIO); } @@ -113,7 +113,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) mpctx->num_tracks = 0; for (int t = 0; t < STREAM_TYPE_COUNT; t++) mpctx->current_track[t] = NULL; - assert(!mpctx->sh_video && !mpctx->sh_audio && !mpctx->sh_sub); + assert(!mpctx->sh_video && !mpctx->d_audio && !mpctx->sh_sub); mpctx->master_demuxer = NULL; for (int i = 0; i < mpctx->num_sources; i++) { uninit_subs(mpctx->sources[i]); @@ -252,20 +252,21 @@ static void print_file_properties(struct MPContext *mpctx) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n", mpctx->sh_video->aspect); } - if (mpctx->sh_audio) { + if (mpctx->d_audio) { + struct sh_audio *sh_audio = mpctx->d_audio->header->audio; /* Assume FOURCC if all bytes >= 0x20 (' ') */ - if (mpctx->sh_audio->format >= 0x20202020) + if (sh_audio->format >= 0x20202020) mp_msg(MSGT_IDENTIFY, MSGL_INFO, - "ID_AUDIO_FORMAT=%.4s\n", (char *)&mpctx->sh_audio->format); + "ID_AUDIO_FORMAT=%.4s\n", (char *)&sh_audio->format); else mp_msg(MSGT_IDENTIFY, MSGL_INFO, - "ID_AUDIO_FORMAT=%d\n", mpctx->sh_audio->format); + "ID_AUDIO_FORMAT=%d\n", sh_audio->format); mp_msg(MSGT_IDENTIFY, MSGL_INFO, - "ID_AUDIO_BITRATE=%d\n", mpctx->sh_audio->i_bps * 8); + "ID_AUDIO_BITRATE=%d\n", sh_audio->i_bps * 8); mp_msg(MSGT_IDENTIFY, MSGL_INFO, - "ID_AUDIO_RATE=%d\n", mpctx->sh_audio->samplerate); + "ID_AUDIO_RATE=%d\n", sh_audio->samplerate); mp_msg(MSGT_IDENTIFY, MSGL_INFO, - "ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels.num); + "ID_AUDIO_NCH=%d\n", sh_audio->channels.num); } mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_LENGTH=%.2f\n", get_time_length(mpctx)); @@ -304,12 +305,12 @@ static void set_demux_field(struct MPContext *mpctx, enum stream_type type, // redundant fields for convenience access switch(type) { case STREAM_VIDEO: mpctx->sh_video = s ? s->video : NULL; break; - case STREAM_AUDIO: mpctx->sh_audio = s ? s->audio : NULL; break; case STREAM_SUB: mpctx->sh_sub = s ? s->sub : NULL; break; } } -void init_demux_stream(struct MPContext *mpctx, enum stream_type type) +struct sh_stream *init_demux_stream(struct MPContext *mpctx, + enum stream_type type) { struct track *track = mpctx->current_track[type]; set_demux_field(mpctx, type, track ? track->stream : NULL); @@ -321,6 +322,7 @@ void init_demux_stream(struct MPContext *mpctx, enum stream_type type) demux_seek(stream->demuxer, pts, SEEK_ABSOLUTE); } } + return stream; } void cleanup_demux_stream(struct MPContext *mpctx, enum stream_type type) @@ -1082,7 +1084,7 @@ static void play_current_file(struct MPContext *mpctx) assert(mpctx->stream == NULL); assert(mpctx->demuxer == NULL); - assert(mpctx->sh_audio == NULL); + assert(mpctx->d_audio == NULL); assert(mpctx->sh_video == NULL); assert(mpctx->sh_sub == NULL); @@ -1229,7 +1231,7 @@ goto_reopen_demuxer: ; //==================== START PLAYING ======================= - if (!mpctx->sh_video && !mpctx->sh_audio) { + if (!mpctx->sh_video && !mpctx->d_audio) { MP_FATAL(mpctx, "No video or audio streams selected.\n"); #if HAVE_DVBIN if (mpctx->stream->type == STREAMTYPE_DVB) { diff --git a/mpvcore/player/main.c b/mpvcore/player/main.c index 4119e244c3..81e724252d 100644 --- a/mpvcore/player/main.c +++ b/mpvcore/player/main.c @@ -194,7 +194,7 @@ static bool handle_help_options(struct MPContext *mpctx) struct MPOpts *opts = mpctx->opts; int opt_exit = 0; if (opts->audio_decoders && strcmp(opts->audio_decoders, "help") == 0) { - struct mp_decoder_list *list = mp_audio_decoder_list(); + struct mp_decoder_list *list = audio_decoder_list(); mp_print_decoders(MSGT_CPLAYER, MSGL_INFO, "Audio decoders:", list); talloc_free(list); opt_exit = 1; diff --git a/mpvcore/player/mp_core.h b/mpvcore/player/mp_core.h index 4e15f49c49..aa0728d10f 100644 --- a/mpvcore/player/mp_core.h +++ b/mpvcore/player/mp_core.h @@ -199,10 +199,11 @@ typedef struct MPContext { struct track *current_track[STREAM_TYPE_COUNT]; struct sh_stream *sh[STREAM_TYPE_COUNT]; - struct sh_audio *sh_audio; // same as sh[STREAM_AUDIO]->audio struct sh_video *sh_video; // same as sh[STREAM_VIDEO]->video struct sh_sub *sh_sub; // same as sh[STREAM_SUB]->sub + struct dec_audio *d_audio; + // Uses: accessing metadata (consider ordered chapters case, where the main // demuxer defines metadata), or special purpose demuxers like TV. struct demuxer *master_demuxer; @@ -357,7 +358,8 @@ struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type, int tid); bool timeline_set_part(struct MPContext *mpctx, int i, bool force); double timeline_set_from_time(struct MPContext *mpctx, double pts, bool *need_reset); -void init_demux_stream(struct MPContext *mpctx, enum stream_type type); +struct sh_stream *init_demux_stream(struct MPContext *mpctx, + enum stream_type type); void cleanup_demux_stream(struct MPContext *mpctx, enum stream_type type); void add_demuxer_tracks(struct MPContext *mpctx, struct demuxer *demuxer); bool mp_remove_track(struct MPContext *mpctx, struct track *track); diff --git a/mpvcore/player/osd.c b/mpvcore/player/osd.c index 03c7c339b7..04052c359e 100644 --- a/mpvcore/player/osd.c +++ b/mpvcore/player/osd.c @@ -108,7 +108,7 @@ void print_status(struct MPContext *mpctx) saddf(&line, "(Paused) "); } - if (mpctx->sh_audio) + if (mpctx->d_audio) saddf(&line, "A"); if (mpctx->sh_video) saddf(&line, "V"); @@ -131,7 +131,7 @@ void print_status(struct MPContext *mpctx) saddf(&line, " x%4.2f", opts->playback_speed); // A-V sync - if (mpctx->sh_audio && sh_video && mpctx->sync_audio_to_video) { + if (mpctx->d_audio && sh_video && mpctx->sync_audio_to_video) { if (mpctx->last_av_difference != MP_NOPTS_VALUE) saddf(&line, " A-V:%7.3f", mpctx->last_av_difference); else diff --git a/mpvcore/player/playloop.c b/mpvcore/player/playloop.c index d611880605..51daf03bb1 100644 --- a/mpvcore/player/playloop.c +++ b/mpvcore/player/playloop.c @@ -96,7 +96,7 @@ void pause_player(struct MPContext *mpctx) if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok) vo_control(mpctx->video_out, VOCTRL_PAUSE, NULL); - if (mpctx->ao && mpctx->sh_audio) + if (mpctx->ao && mpctx->d_audio) ao_pause(mpctx->ao); // pause audio, keep data if possible // Only print status if there's actually a file being played. @@ -124,7 +124,7 @@ void unpause_player(struct MPContext *mpctx) mpctx->paused = false; mpctx->osd_function = 0; - if (mpctx->ao && mpctx->sh_audio) + if (mpctx->ao && mpctx->d_audio) ao_resume(mpctx->ao); if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok) vo_control(mpctx->video_out, VOCTRL_RESUME, NULL); // resume video @@ -182,10 +182,10 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao) mpctx->time_frame = 0; } - if (mpctx->sh_audio) { - resync_audio_stream(mpctx->sh_audio); - if (mpctx->sh_audio->afilter) - af_control_all(mpctx->sh_audio->afilter, AF_CONTROL_RESET, NULL); + if (mpctx->d_audio) { + audio_resync_stream(mpctx->d_audio); + if (mpctx->d_audio->afilter) + af_control_all(mpctx->d_audio->afilter, AF_CONTROL_RESET, NULL); if (reset_ao) clear_audio_output_buffers(mpctx); clear_audio_decode_buffers(mpctx); @@ -255,7 +255,7 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek, if (demuxer_amount == -1) { assert(!need_reset); mpctx->stop_play = AT_END_OF_FILE; - if (mpctx->sh_audio && !timeline_fallthrough) { + if (mpctx->d_audio && !timeline_fallthrough) { // Seek outside of the file -> clear audio from current position clear_audio_decode_buffers(mpctx); clear_audio_output_buffers(mpctx); @@ -589,7 +589,7 @@ do_seek: static void update_avsync(struct MPContext *mpctx) { - if (!mpctx->sh_audio || !mpctx->sh_video) + if (!mpctx->d_audio || !mpctx->sh_video) return; double a_pos = playing_audio_pts(mpctx); @@ -620,7 +620,7 @@ static void adjust_sync(struct MPContext *mpctx, double frame_time) { struct MPOpts *opts = mpctx->opts; - if (!mpctx->sh_audio || mpctx->syncing_audio) + if (!mpctx->d_audio || mpctx->syncing_audio) return; double a_pts = written_audio_pts(mpctx) - mpctx->delay; @@ -969,7 +969,7 @@ void run_playloop(struct MPContext *mpctx) mpctx->stop_play = PT_NEXT_ENTRY; } - if (mpctx->sh_audio && !mpctx->restart_playback && !mpctx->ao->untimed) { + if (mpctx->d_audio && !mpctx->restart_playback && !mpctx->ao->untimed) { int status = fill_audio_out_buffers(mpctx, endpts); full_audio_buffers = status >= 0; // Not at audio stream EOF yet @@ -1118,7 +1118,7 @@ void run_playloop(struct MPContext *mpctx) if (mpctx->restart_playback) { if (mpctx->sync_audio_to_video) { mpctx->syncing_audio = true; - if (mpctx->sh_audio) + if (mpctx->d_audio) fill_audio_out_buffers(mpctx, endpts); mpctx->restart_playback = false; } @@ -1135,9 +1135,9 @@ void run_playloop(struct MPContext *mpctx) video_left &= mpctx->sync_audio_to_video; // force no-video semantics - if (mpctx->sh_audio && (mpctx->restart_playback ? !video_left : - mpctx->ao->untimed && (mpctx->delay <= 0 || - !video_left))) { + if (mpctx->d_audio && (mpctx->restart_playback ? !video_left : + mpctx->ao->untimed && (mpctx->delay <= 0 || + !video_left))) { int status = fill_audio_out_buffers(mpctx, endpts); full_audio_buffers = status >= 0 && !mpctx->ao->untimed; // Not at audio stream EOF yet @@ -1145,7 +1145,7 @@ void run_playloop(struct MPContext *mpctx) } if (!video_left) mpctx->restart_playback = false; - if (mpctx->sh_audio && buffered_audio == -1) + if (mpctx->d_audio && buffered_audio == -1) buffered_audio = mpctx->paused ? 0 : ao_get_delay(mpctx->ao); update_osd_msg(mpctx); @@ -1156,7 +1156,7 @@ void run_playloop(struct MPContext *mpctx) if (!video_left && (!mpctx->paused || was_restart)) { double a_pos = 0; - if (mpctx->sh_audio) { + if (mpctx->d_audio) { a_pos = (written_audio_pts(mpctx) - mpctx->opts->playback_speed * buffered_audio); } @@ -1182,7 +1182,7 @@ void run_playloop(struct MPContext *mpctx) * should trigger after seek only, when we know there's no audio * buffered. */ - if ((mpctx->sh_audio || mpctx->sh_video) && !audio_left && !video_left + if ((mpctx->d_audio || mpctx->sh_video) && !audio_left && !video_left && (opts->gapless_audio || buffered_audio < 0.05) && (!mpctx->paused || was_restart)) { if (end_is_chapter) { @@ -1227,7 +1227,7 @@ void run_playloop(struct MPContext *mpctx) if (!mpctx->stop_play) { double audio