summaryrefslogtreecommitdiffstats
path: root/libmpcodecs/ad_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmpcodecs/ad_pcm.c')
-rw-r--r--libmpcodecs/ad_pcm.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/libmpcodecs/ad_pcm.c b/libmpcodecs/ad_pcm.c
index 8788a2e1cd..a5a17e1a49 100644
--- a/libmpcodecs/ad_pcm.c
+++ b/libmpcodecs/ad_pcm.c
@@ -20,12 +20,13 @@
#include <stdlib.h>
#include <unistd.h>
+#include "talloc.h"
#include "config.h"
#include "ad_internal.h"
#include "libaf/af_format.h"
#include "libaf/reorder_ch.h"
-static ad_info_t info =
+static const ad_info_t info =
{
"Uncompressed PCM audio decoder",
"pcm",
@@ -34,6 +35,11 @@ static ad_info_t info =
""
};
+struct ad_pcm_context {
+ unsigned char *packet_ptr;
+ int packet_len;
+};
+
LIBAD_EXTERN(pcm)
static int init(sh_audio_t *sh_audio)
@@ -111,6 +117,7 @@ static int init(sh_audio_t *sh_audio)
}
if (!sh_audio->samplesize) // this would cause MPlayer to hang later
sh_audio->samplesize = 2;
+ sh_audio->context = talloc_zero(NULL, struct ad_pcm_context);
return 1;
}
@@ -122,6 +129,7 @@ static int preinit(sh_audio_t *sh)
static void uninit(sh_audio_t *sh)
{
+ talloc_free(sh->context);
}
static int control(sh_audio_t *sh,int cmd,void* arg, ...)
@@ -141,12 +149,37 @@ static int control(sh_audio_t *sh,int cmd,void* arg, ...)
static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
{
unsigned len = sh_audio->channels*sh_audio->samplesize;
- len = (minlen + len - 1) / len * len;
- if (len > maxlen)
+ minlen = (minlen + len - 1) / len * len;
+ if (minlen > maxlen)
// if someone needs hundreds of channels adjust audio_out_minsize
// based on channels in preinit()
return -1;
- len=demux_read_data(sh_audio->ds,buf,len);
+
+ len = 0;
+ struct ad_pcm_context *ctx = sh_audio->context;
+ while (len < minlen) {
+ if (ctx->packet_len == 0) {
+ double pts;
+ int plen = ds_get_packet_pts(sh_audio->ds, &ctx->packet_ptr, &pts);
+ if (plen < 0)
+ break;
+ ctx->packet_len = plen;
+ if (pts != MP_NOPTS_VALUE) {
+ sh_audio->pts = pts;
+ sh_audio->pts_bytes = 0;
+ }
+ }
+ int from_stored = ctx->packet_len;
+ if (from_stored > minlen - len)
+ from_stored = minlen - len;
+ memcpy(buf + len, ctx->packet_ptr, from_stored);
+ ctx->packet_len -= from_stored;
+ ctx->packet_ptr += from_stored;
+ sh_audio->pts_bytes += from_stored;
+ len += from_stored;
+ }
+ if (len == 0)
+ len = -1; // The loop above only exits at error/EOF
if (len > 0 && sh_audio->channels >= 5) {
reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT,
AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,