aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--audio/decode/ad.h11
-rw-r--r--audio/decode/ad_lavc.c68
-rw-r--r--audio/decode/ad_mpg123.c110
-rw-r--r--audio/decode/ad_spdif.c30
-rw-r--r--audio/decode/dec_audio.c161
-rw-r--r--audio/decode/dec_audio.h30
-rw-r--r--demux/stheader.h5
-rw-r--r--mpvcore/player/audio.c85
-rw-r--r--mpvcore/player/command.c32
-rw-r--r--mpvcore/player/loadfile.c30
-rw-r--r--mpvcore/player/main.c2
-rw-r--r--mpvcore/player/mp_core.h6
-rw-r--r--mpvcore/player/osd.c4
-rw-r--r--mpvcore/player/playloop.c36
-rw-r--r--mpvcore/player/video.c8
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;
}