summaryrefslogtreecommitdiffstats
path: root/audio/decode/dec_audio.c
diff options
context:
space:
mode:
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);
}