summaryrefslogtreecommitdiffstats
path: root/audio/decode
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-11-23 21:22:17 +0100
committerwm4 <wm4@nowhere>2013-11-23 21:22:17 +0100
commit0f5ec05d8f4ae02262dc79a895bce3b465b376f2 (patch)
treeba5fc3f640eeefa44a28695f8cd3f63ba2eec2c9 /audio/decode
parent705a7310e6c823a72c961720f8ae416962f1398a (diff)
downloadmpv-0f5ec05d8f4ae02262dc79a895bce3b465b376f2.tar.bz2
mpv-0f5ec05d8f4ae02262dc79a895bce3b465b376f2.tar.xz
audio: move decoder context from sh_audio into new struct
Move all state that basically changes during decoding or is needed in order to manage decoding itself into a new struct (dec_audio). sh_audio (defined in stheader.h) is supposed to be the audio stream header. This should reflect the file headers for the stream. Putting the decoder context there is strange design, to say the least.
Diffstat (limited to 'audio/decode')
-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
6 files changed, 219 insertions, 191 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);