summaryrefslogtreecommitdiffstats
path: root/audio/decode/dec_audio.c
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/dec_audio.c
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/dec_audio.c')
-rw-r--r--audio/decode/dec_audio.c161
1 files changed, 86 insertions, 75 deletions
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);
}