From 347a86198b214b5e79b45d198c5cd2cc3c3a759a Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:38:18 +0100 Subject: audio: switch output to mp_audio_buffer Replace the code that used a single buffer with mp_audio_buffer. This also enables non-interleaved output operation, although it's still disabled, and no AO supports it yet. --- audio/decode/dec_audio.c | 54 +++++++++++++++++------------------------------- audio/decode/dec_audio.h | 7 +++---- audio/out/ao.c | 12 ++++++----- audio/out/ao.h | 6 +++--- 4 files changed, 32 insertions(+), 47 deletions(-) (limited to 'audio') diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index ef7993c83a..3f92c3c4e6 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -38,6 +38,7 @@ #include "dec_audio.h" #include "ad.h" #include "audio/format.h" +#include "audio/audio_buffer.h" #include "audio/filter/af.h" @@ -230,18 +231,9 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, return 1; } -static void set_min_out_buffer_size(struct bstr *outbuf, int len) -{ - size_t oldlen = talloc_get_size(outbuf->start); - if (oldlen < len) { - assert(outbuf->start); // talloc context should be already set - mp_msg(MSGT_DECAUDIO, MSGL_V, "Increasing filtered audio buffer size " - "from %zd to %d\n", oldlen, len); - outbuf->start = talloc_realloc_size(NULL, outbuf->start, len); - } -} - -static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) +// Filter len bytes of input, put result into outbuf. +static int filter_n_bytes(sh_audio_t *sh, struct mp_audio_buffer *outbuf, + int len) { assert(len - 1 + sh->audio_out_minsize <= sh->a_buffer_size); @@ -280,10 +272,7 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) struct mp_audio *filter_output = af_play(sh->afilter, &filter_input); if (!filter_output) return -1; - int outlen = filter_output->samples * filter_output->sstride; - set_min_out_buffer_size(outbuf, outbuf->len + outlen); - memcpy(outbuf->start + outbuf->len, filter_output->planes[0], outlen); - outbuf->len += outlen; + mp_audio_buffer_append(outbuf, filter_output); // remove processed data from decoder buffer: sh->a_buffer_len -= len; @@ -292,20 +281,20 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) return error; } -/* Try to get at least minlen decoded+filtered bytes in outbuf +/* 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). - * In the former case outbuf->len is always >= minlen on return. - * In case of EOF/error it might or might not be. - * Outbuf.start must be talloc-allocated, and will be reallocated - * if needed to fit all filter output. */ -int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen) + * 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 minsamples) { // Indicates that a filter seems to be buffering large amounts of data int huge_filter_buffer = 0; + int sstride = + af_fmt2bits(sh_audio->sample_format) / 8 * sh_audio->channels.num; // Decoded audio must be cut at boundaries of this many bytes - int bps = af_fmt2bits(sh_audio->sample_format) / 8; - int unitsize = sh_audio->channels.num * bps * 16; + int unitsize = sstride * 16; /* Filter output size will be about filter_multiplier times input size. * If some filter buffers audio in big blocks this might only hold @@ -322,9 +311,13 @@ int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen) return -1; max_decode_len -= max_decode_len % unitsize; - while (minlen >= 0 && outbuf->len < minlen) { + while (minsamples >= 0 && mp_audio_buffer_samples(outbuf) < minsamples) { + struct af_stream *afs = sh_audio->afilter; + int out_sstride = afs->output.sstride; + int declen = (minsamples - mp_audio_buffer_samples(outbuf)) + * out_sstride / filter_multiplier; // + some extra for possible filter buffering - int declen = (minlen - outbuf->len) / filter_multiplier + (unitsize << 5); + declen += unitsize << 5; if (huge_filter_buffer) /* Some filter must be doing significant buffering if the estimated * input length didn't produce enough output from filters. @@ -349,15 +342,6 @@ int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen) return 0; } -void decode_audio_prepend_bytes(struct bstr *outbuf, int count, int byte) -{ - set_min_out_buffer_size(outbuf, outbuf->len + count); - memmove(outbuf->start + count, outbuf->start, outbuf->len); - memset(outbuf->start, byte, count); - outbuf->len += count; -} - - void resync_audio_stream(sh_audio_t *sh_audio) { sh_audio->pts = MP_NOPTS_VALUE; diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h index b46f4282fb..3ec5954471 100644 --- a/audio/decode/dec_audio.h +++ b/audio/decode/dec_audio.h @@ -22,15 +22,14 @@ #include "audio/chmap.h" #include "demux/stheader.h" -struct bstr; +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 bstr *outbuf, int minlen); -void decode_audio_prepend_bytes(struct bstr *outbuf, int count, int byte); +int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, + int minsamples); void resync_audio_stream(sh_audio_t *sh_audio); -void skip_audio_frame(sh_audio_t *sh_audio); void uninit_audio(sh_audio_t *sh_audio); int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, diff --git a/audio/out/ao.c b/audio/out/ao.c index fd20270160..50c95830c3 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -209,10 +209,9 @@ void ao_uninit(struct ao *ao, bool cut_audio) talloc_free(ao); } -int ao_play(struct ao *ao, void *data, int len, int flags) +int ao_play(struct ao *ao, void **data, int samples, int flags) { - int r = ao->driver->play(ao, &data, len / ao->sstride, flags); - return r < 0 ? r : r * ao->sstride; + return ao->driver->play(ao, data, samples, flags); } int ao_control(struct ao *ao, enum aocontrol cmd, void *arg) @@ -233,7 +232,7 @@ double ao_get_delay(struct ao *ao) int ao_get_space(struct ao *ao) { - return ao->driver->get_space(ao) * ao->sstride; + return ao->driver->get_space(ao); } void ao_reset(struct ao *ao) @@ -260,7 +259,10 @@ int ao_play_silence(struct ao *ao, int samples) return 0; char *p = talloc_size(NULL, samples * ao->sstride); af_fill_silence(p, samples * ao->sstride, ao->format); - int r = ao_play(ao, p, samples * ao->sstride, 0); + void *tmp[MP_NUM_CHANNELS]; + for (int n = 0; n < MP_NUM_CHANNELS; n++) + tmp[n] = p; + int r = ao_play(ao, tmp, samples, 0); talloc_free(p); return r; } diff --git a/audio/out/ao.h b/audio/out/ao.h index eb1af990ff..dff9ad6a8b 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -76,8 +76,8 @@ struct ao { int sstride; // size of a sample on each plane // (format_size*num_channels/num_planes) double pts; // some mplayer.c state (why is this here?) - struct bstr buffer; - int buffer_playable_size; // part of the part of the buffer the AO hasn't + struct mp_audio_buffer *buffer; // queued audio; passed to play() later + int buffer_playable_samples;// part of the part of the buffer the AO hasn't // accepted yet with play() bool probing; // if true, don't fail loudly on init bool untimed; @@ -97,7 +97,7 @@ struct ao *ao_init_best(struct mpv_global *global, struct encode_lavc_context *encode_lavc_ctx, int samplerate, int format, struct mp_chmap channels); void ao_uninit(struct ao *ao, bool cut_audio); -int ao_play(struct ao *ao, void *data, int len, int flags); +int ao_play(struct ao *ao, void **data, int samples, int flags); int ao_control(struct ao *ao, enum aocontrol cmd, void *arg); double ao_get_delay(struct ao *ao); int ao_get_space(struct ao *ao); -- cgit v1.2.3