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