diff options
-rw-r--r-- | audio/decode/ad.h | 11 | ||||
-rw-r--r-- | audio/decode/ad_lavc.c | 68 | ||||
-rw-r--r-- | audio/decode/ad_mpg123.c | 110 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 30 | ||||
-rw-r--r-- | audio/decode/dec_audio.c | 161 | ||||
-rw-r--r-- | audio/decode/dec_audio.h | 30 | ||||
-rw-r--r-- | demux/stheader.h | 5 | ||||
-rw-r--r-- | mpvcore/player/audio.c | 85 | ||||
-rw-r--r-- | mpvcore/player/command.c | 32 | ||||
-rw-r--r-- | mpvcore/player/loadfile.c | 30 | ||||
-rw-r--r-- | mpvcore/player/main.c | 2 | ||||
-rw-r--r-- | mpvcore/player/mp_core.h | 6 | ||||
-rw-r--r-- | mpvcore/player/osd.c | 4 | ||||
-rw-r--r-- | mpvcore/player/playloop.c | 36 | ||||
-rw-r--r-- | 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 : "<unknown>"); + d_audio->header->codec ? d_audio->header->codec : "<unknown>"); } 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_sleep = 9; - if (mpctx->sh_audio && !mpctx->paused) { + if (mpctx->d_audio && !mpctx->paused) { if (mpctx->ao->untimed) { if (!video_left) audio_sleep = 0; diff --git a/mpvcore/player/video.c b/mpvcore/player/video.c index 66c6216d30..d55a19e79f 100644 --- a/mpvcore/player/video.c +++ b/mpvcore/player/video.c @@ -243,8 +243,8 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time) { struct MPOpts *opts = mpctx->opts; // check for frame-drop: - if (mpctx->sh_audio && !mpctx->ao->untimed && - !demux_stream_eof(mpctx->sh_audio->gsh)) + if (mpctx->d_audio && !mpctx->ao->untimed && + !demux_stream_eof(mpctx->sh[STREAM_AUDIO])) { float delay = opts->playback_speed * ao_get_delay(mpctx->ao); float d = delay - mpctx->delay; @@ -314,7 +314,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) struct demux_packet *pkt = video_read_frame(mpctx); if (!pkt) return -1; - if (mpctx->sh_audio) + if (mpctx->d_audio) mpctx->delay -= frame_time; // video_read_frame can change fps (e.g. for ASF video) update_fps(mpctx); @@ -469,7 +469,7 @@ double update_video(struct MPContext *mpctx, double endpts) } double frame_time = sh_video->pts - sh_video->last_pts; sh_video->last_pts = sh_video->pts; - if (mpctx->sh_audio) + if (mpctx->d_audio) mpctx->delay -= frame_time; return frame_time; } |