summaryrefslogtreecommitdiffstats
path: root/audio/decode/ad_mpg123.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-07-21 19:29:37 +0200
committerwm4 <wm4@nowhere>2014-07-21 19:29:58 +0200
commitb6af44d31e5c00b512e4c64b7075b771286e7c74 (patch)
tree0590b1095d13c61a538d622c1383f96554f27c85 /audio/decode/ad_mpg123.c
parent1f9e0a15a13f9b1efece10515c57e5ed4683e9f3 (diff)
downloadmpv-b6af44d31e5c00b512e4c64b7075b771286e7c74.tar.bz2
mpv-b6af44d31e5c00b512e4c64b7075b771286e7c74.tar.xz
audio: move initial decode to generic code
This commit mainly moves the initial decoding of data (done to probe the audio format) to generic code. This will make it easier to make audio decoding non-blocking in a later commit. This commit also changes how decoders return data: instead of having them write the data into a prepared buffer, they return a reference to an internal buffer (by setting dec_audio.decoded). This makes it significantly easier to handle audio format changes, since the decoders don't really need to care anymore.
Diffstat (limited to 'audio/decode/ad_mpg123.c')
-rw-r--r--audio/decode/ad_mpg123.c210
1 files changed, 68 insertions, 142 deletions
diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c
index 055285cccd..f96a5a8036 100644
--- a/audio/decode/ad_mpg123.c
+++ b/audio/decode/ad_mpg123.c
@@ -35,9 +35,7 @@
struct ad_mpg123_context {
mpg123_handle *handle;
- bool new_format;
int sample_size;
- bool need_data;
/* Running mean for bit rate, stream length estimation. */
float mean_rate;
unsigned int mean_count;
@@ -58,7 +56,7 @@ static void uninit(struct dec_audio *da)
/* This initializes libmpg123 and prepares the handle, including funky
* parameters. */
-static int preinit(struct dec_audio *da)
+static int init(struct dec_audio *da, const char *decoder)
{
int err;
struct ad_mpg123_context *con;
@@ -111,15 +109,18 @@ static int preinit(struct dec_audio *da)
* We need at least 1152 samples. dec_audio.c normally guarantees this. */
mpg123_param(con->handle, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 0.);
+ err = mpg123_open_feed(con->handle);
+ if (err != MPG123_OK)
+ goto bad_end;
+
return 1;
bad_end:
- if (!con->handle)
- MP_ERR(da, "mpg123 preinit error: %s\n",
- mpg123_plain_strerror(err));
- else
- MP_ERR(da, "mpg123 preinit error: %s\n",
- mpg123_strerror(con->handle));
+ if (!con->handle) {
+ MP_ERR(da, "mpg123 preinit error: %s\n", mpg123_plain_strerror(err));
+ } else {
+ MP_ERR(da, "mpg123 preinit error: %s\n", mpg123_strerror(con->handle));
+ }
uninit(da);
return 0;
@@ -140,111 +141,6 @@ static int mpg123_format_to_af(int mpg123_encoding)
return 0;
}
-/* libmpg123 has a new format ready; query and store, return return value
- of mpg123_getformat() */
-static int set_format(struct dec_audio *da)
-{
- 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_audio_set_num_channels(&da->decoded, channels);
- da->decoded.rate = 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_ERR(da, "Bad encoding from mpg123: %i.\n", encoding);
- return MPG123_ERR;
- }
- mp_audio_set_format(&da->decoded, af);
- con->sample_size = channels * af_fmt2bps(af);
- con->new_format = 0;
- }
- return ret;
-}
-
-static int feed_new_packet(struct dec_audio *da)
-{
- struct ad_mpg123_context *con = da->priv;
- int ret;
-
- 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) {
- da->pts = pkt->pts;
- da->pts_offset = 0;
- }
-
- /* Have to use mpg123_feed() to avoid decoding here. */
- ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
- talloc_free(pkt);
-
- if (ret == MPG123_ERR)
- return -1;
-
- if (ret == MPG123_NEW_FORMAT)
- con->new_format = 1;
-
- return 0;
-}
-
-/* Now we really start accessing some data and determining file format.
- * 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(struct dec_audio *da, const char *decoder)
-{
- if (!preinit(da))
- return 0;
-
- struct ad_mpg123_context *con = da->priv;
- int ret;
-
- ret = mpg123_open_feed(con->handle);
- if (ret != MPG123_OK)
- goto fail;
-
- for (int n = 0; ; n++) {
- 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(da);
- if (ret == MPG123_OK)
- break;
- }
- if (ret != MPG123_NEED_MORE)
- goto fail;
- // max. 16 retries (randomly chosen number)
- if (n > 16) {
- ret = MPG123_NEED_MORE;
- goto fail;
- }
- }
-
- return 1;
-
-fail:
- if (ret == MPG123_NEED_MORE) {
- MP_ERR(da, "Could not find mp3 stream.\n");
- } else {
- MP_ERR(da, "mpg123 init error: %s\n",
- mpg123_strerror(con->handle));
- }
-
- uninit(da);
- return 0;
-}
-
/* Compute bitrate from frame size. */
static int compute_bitrate(struct mpg123_frameinfo *i)
{
@@ -290,50 +186,79 @@ static void update_info(struct dec_audio *da)
}
}
-static int decode_audio(struct dec_audio *da, struct mp_audio *buffer, int maxlen)
+/* libmpg123 has a new format ready; query and store, return return value
+ of mpg123_getformat() */
+static int set_format(struct dec_audio *da)
{
struct ad_mpg123_context *con = da->priv;
- void *buf = buffer->planes[0];
int ret;
-
- if (con->new_format) {
- ret = set_format(da);
- if (ret == MPG123_OK) {
- return 0; // let caller handle format change
- } else if (ret == MPG123_NEED_MORE) {
- con->need_data = true;
- } else {
- goto mpg123_fail;
+ long rate;
+ int channels;
+ int encoding;
+ ret = mpg123_getformat(con->handle, &rate, &channels, &encoding);
+ if (ret == MPG123_OK) {
+ mp_audio_set_num_channels(&da->decoded, channels);
+ da->decoded.rate = 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_ERR(da, "Bad encoding from mpg123: %i.\n", encoding);
+ return MPG123_ERR;
}
+ mp_audio_set_format(&da->decoded, af);
+ con->sample_size = channels * af_fmt2bps(af);
}
+ return ret;
+}
- if (con->need_data) {
- if (feed_new_packet(da) < 0)
- return AD_ERR;
+static int decode_packet(struct dec_audio *da)
+{
+ struct ad_mpg123_context *con = da->priv;
+ int ret;
+
+ mp_audio_set_null_data(&da->decoded);
+
+ struct demux_packet *pkt = demux_read_packet(da->header);
+ if (!pkt)
+ return AD_EOF;
+
+ /* Next bytes from that presentation time. */
+ if (pkt->pts != MP_NOPTS_VALUE) {
+ da->pts = pkt->pts;
+ da->pts_offset = 0;
}
- if (!mp_audio_config_equals(&da->decoded, buffer))
- return 0;
+ /* Have to use mpg123_feed() to avoid decoding here. */
+ ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
+ talloc_free(pkt);
- size_t got_now = 0;
- ret = mpg123_replace_buffer(con->handle, buf, maxlen * con->sample_size);
if (ret != MPG123_OK)
goto mpg123_fail;
- ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now);
+ unsigned char *audio = NULL;
+ size_t bytes = 0;
+ ret = mpg123_decode_frame(con->handle, NULL, &audio, &bytes);
- int got_samples = got_now / con->sample_size;
- buffer->samples += got_samples;
- da->pts_offset += got_samples;
+ if (ret == MPG123_NEED_MORE)
+ return 0;
+
+ if (ret != MPG123_OK && ret != MPG123_DONE && ret != MPG123_NEW_FORMAT)
+ goto mpg123_fail;
- if (ret == MPG123_NEW_FORMAT) {
- con->new_format = true;
- } else if (ret == MPG123_NEED_MORE) {
- con->need_data = true;
- } else if (ret != MPG123_OK && ret != MPG123_DONE) {
+ ret = set_format(da);
+ if (ret != MPG123_OK)
goto mpg123_fail;
+
+ if (con->sample_size < 1) {
+ MP_ERR(da, "no sample size\n");
+ return AD_ERR;
}
+ int got_samples = bytes / con->sample_size;
+ da->decoded.planes[0] = audio;
+ da->decoded.samples = got_samples;
+ da->pts_offset += got_samples;
+
update_info(da);
return 0;
@@ -348,6 +273,7 @@ static int control(struct dec_audio *da, int cmd, void *arg)
switch (cmd) {
case ADCTRL_RESET:
+ mp_audio_set_null_data(&da->decoded);
mpg123_close(con->handle);
if (mpg123_open_feed(con->handle) != MPG123_OK) {
@@ -372,5 +298,5 @@ const struct ad_functions ad_mpg123 = {
.init = init,
.uninit = uninit,
.control = control,
- .decode_audio = decode_audio,
+ .decode_packet = decode_packet,
};