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.
This commit is contained in:
Uoti Urpala 2008-08-03 21:14:11 +03:00
parent 6cce822505
commit 2ba9df3df3
1 changed files with 36 additions and 3 deletions

View File

@ -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,