diff options
author | Uoti Urpala <uau@symbol.nonexistent.invalid> | 2008-08-03 21:14:11 +0300 |
---|---|---|
committer | Uoti Urpala <uau@symbol.nonexistent.invalid> | 2008-08-03 21:25:48 +0300 |
commit | 2ba9df3df3d61a7cc1bde9f897bc77eaaf14b383 (patch) | |
tree | ba2664cf554237fde25eac4718fb17ed63c37b08 | |
parent | 6cce822505c0a76ac520909a895021b8f5b7e5ab (diff) | |
download | mpv-2ba9df3df3d61a7cc1bde9f897bc77eaaf14b383.tar.bz2 mpv-2ba9df3df3d61a7cc1bde9f897bc77eaaf14b383.tar.xz |
ad_pcm: Track pts explicitly
ad_pcm used the old audio timestamp tracking system that calculated
timestamp at end of decoder output as
last_timestamp_in_input_decoder_has_read +
bytes_read_after_that_timestamp / input_bitrate.
For PCM this can be accurate as input bitrate is constant. However it
relies on input bitrate being known and actually set. At least in some
case with .mov input and libavformat demuxer it wasn't set. Instead of
special-casing PCM to make sure input bitrate is set (in general it
may not be known or constant at all) change ad_pcm to explicitly set
the pts information on the decoder output side.
-rw-r--r-- | libmpcodecs/ad_pcm.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/libmpcodecs/ad_pcm.c b/libmpcodecs/ad_pcm.c index 1c2ef53813..058f6c25cb 100644 --- a/libmpcodecs/ad_pcm.c +++ b/libmpcodecs/ad_pcm.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <unistd.h> +#include "talloc.h" #include "config.h" #include "ad_internal.h" #include "libaf/af_format.h" @@ -16,6 +17,11 @@ static const 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) @@ -91,6 +97,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; } @@ -102,6 +109,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, ...) @@ -121,12 +129,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, |