lavf: Add system to seperate relative timestamps from absolute ones.

With this we can always know if a timestamp is based on added durations
from an unknown origin or if it is based on a correct timestamp (and possibly
added durations)
This should fix some bugs where this distinction was mixed up.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-03-07 22:13:39 +01:00
parent d07de6d75d
commit ad53c7f9ec
4 changed files with 42 additions and 19 deletions

View File

@ -4258,6 +4258,7 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
// FIXME: a more elegant solution is needed // FIXME: a more elegant solution is needed
memcpy(st, ic->streams[i], sizeof(AVStream)); memcpy(st, ic->streams[i], sizeof(AVStream));
st->cur_dts = 0;
st->info = av_malloc(sizeof(*st->info)); st->info = av_malloc(sizeof(*st->info));
memcpy(st->info, ic->streams[i]->info, sizeof(*st->info)); memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
st->codec= avctx; st->codec= avctx;

View File

@ -72,6 +72,12 @@ const char *avformat_license(void)
return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
} }
#define RELATIVE_TS_BASE (INT64_MAX - (1LL<<32))
static int is_relative(int64_t ts) {
return ts > (RELATIVE_TS_BASE - (1LL<<32));
}
/* fraction handling */ /* fraction handling */
/** /**
@ -870,21 +876,23 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
AVStream *st= s->streams[stream_index]; AVStream *st= s->streams[stream_index];
AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer;
if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE) if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE || is_relative(dts))
return; return;
st->first_dts= dts - st->cur_dts; st->first_dts= dts - (st->cur_dts - RELATIVE_TS_BASE);
st->cur_dts= dts; st->cur_dts= dts;
if (is_relative(pts))
pts += st->first_dts - RELATIVE_TS_BASE;
for(; pktl; pktl= get_next_pkt(s, st, pktl)){ for(; pktl; pktl= get_next_pkt(s, st, pktl)){
if(pktl->pkt.stream_index != stream_index) if(pktl->pkt.stream_index != stream_index)
continue; continue;
//FIXME think more about this check if(is_relative(pktl->pkt.pts))
if(pktl->pkt.pts != AV_NOPTS_VALUE && pktl->pkt.pts == pktl->pkt.dts) pktl->pkt.pts += st->first_dts - RELATIVE_TS_BASE;
pktl->pkt.pts += st->first_dts;
if(pktl->pkt.dts != AV_NOPTS_VALUE) if(is_relative(pktl->pkt.dts))
pktl->pkt.dts += st->first_dts; pktl->pkt.dts += st->first_dts - RELATIVE_TS_BASE;
if(st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE) if(st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE)
st->start_time= pktl->pkt.pts; st->start_time= pktl->pkt.pts;
@ -897,7 +905,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st,
int stream_index, int duration) int stream_index, int duration)
{ {
AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer;
int64_t cur_dts= 0; int64_t cur_dts= RELATIVE_TS_BASE;
if(st->first_dts != AV_NOPTS_VALUE){ if(st->first_dts != AV_NOPTS_VALUE){
cur_dts= st->first_dts; cur_dts= st->first_dts;
@ -910,7 +918,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st,
} }
pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; pktl= s->parse_queue ? s->parse_queue : s->packet_buffer;
st->first_dts = cur_dts; st->first_dts = cur_dts;
}else if(st->cur_dts) }else if(st->cur_dts != RELATIVE_TS_BASE)
return; return;
for(; pktl; pktl= get_next_pkt(s, st, pktl)){ for(; pktl; pktl= get_next_pkt(s, st, pktl)){
@ -1308,15 +1316,17 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{ {
const int genpts = s->flags & AVFMT_FLAG_GENPTS; const int genpts = s->flags & AVFMT_FLAG_GENPTS;
int eof = 0; int eof = 0;
int ret;
if (!genpts) if (!genpts) {
return s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer, ret = s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer,
&s->packet_buffer_end, &s->packet_buffer_end,
pkt) : pkt) :
read_frame_internal(s, pkt); read_frame_internal(s, pkt);
goto return_packet;
}
for (;;) { for (;;) {
int ret;
AVPacketList *pktl = s->packet_buffer; AVPacketList *pktl = s->packet_buffer;
if (pktl) { if (pktl) {
@ -1337,9 +1347,11 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
/* read packet from packet buffer, if there is data */ /* read packet from packet buffer, if there is data */
if (!(next_pkt->pts == AV_NOPTS_VALUE && if (!(next_pkt->pts == AV_NOPTS_VALUE &&
next_pkt->dts != AV_NOPTS_VALUE && !eof)) next_pkt->dts != AV_NOPTS_VALUE && !eof)) {
return read_from_packet_buffer(&s->packet_buffer, ret = read_from_packet_buffer(&s->packet_buffer,
&s->packet_buffer_end, pkt); &s->packet_buffer_end, pkt);
goto return_packet;
}
} }
ret = read_frame_internal(s, pkt); ret = read_frame_internal(s, pkt);
@ -1355,6 +1367,13 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
&s->packet_buffer_end)) < 0) &s->packet_buffer_end)) < 0)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
return_packet:
if (is_relative(pkt->dts))
pkt->dts -= RELATIVE_TS_BASE;
if (is_relative(pkt->pts))
pkt->pts -= RELATIVE_TS_BASE;
return ret;
} }
/* XXX: suppress the packet queue */ /* XXX: suppress the packet queue */
@ -1408,7 +1427,7 @@ void ff_read_frame_flush(AVFormatContext *s)
st->parser = NULL; st->parser = NULL;
} }
st->last_IP_pts = AV_NOPTS_VALUE; st->last_IP_pts = AV_NOPTS_VALUE;
if(st->first_dts == AV_NOPTS_VALUE) st->cur_dts = 0; if(st->first_dts == AV_NOPTS_VALUE) st->cur_dts = RELATIVE_TS_BASE;
else st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ else st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */
st->reference_dts = AV_NOPTS_VALUE; st->reference_dts = AV_NOPTS_VALUE;
@ -1456,6 +1475,9 @@ int ff_add_index_entry(AVIndexEntry **index_entries,
if((unsigned)*nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry)) if((unsigned)*nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
return -1; return -1;
if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known
timestamp -= RELATIVE_TS_BASE;
entries = av_fast_realloc(*index_entries, entries = av_fast_realloc(*index_entries,
index_entries_allocated_size, index_entries_allocated_size,
(*nb_index_entries + 1) * (*nb_index_entries + 1) *
@ -2479,7 +2501,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int64_t last = st->info->last_dts; int64_t last = st->info->last_dts;
if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){ if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){
double dts= pkt->dts * av_q2d(st->time_base); double dts= (is_relative(pkt->dts) ? pkt->dts - RELATIVE_TS_BASE : pkt->dts) * av_q2d(st->time_base);
int64_t duration= pkt->dts - last; int64_t duration= pkt->dts - last;
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
@ -2883,7 +2905,7 @@ AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)
but durations get some timestamps, formats with some unknown but durations get some timestamps, formats with some unknown
timestamps have their first few packets buffered and the timestamps have their first few packets buffered and the
timestamps corrected before they are returned to the user */ timestamps corrected before they are returned to the user */
st->cur_dts = 0; st->cur_dts = s->iformat ? RELATIVE_TS_BASE : 0;
st->first_dts = AV_NOPTS_VALUE; st->first_dts = AV_NOPTS_VALUE;
st->probe_packets = MAX_PROBE_PACKETS; st->probe_packets = MAX_PROBE_PACKETS;

View File

@ -1,3 +1,3 @@
7bd312f32538a14f248c2dff85394118 *./tests/data/lavf/lavf.wtv 7bd312f32538a14f248c2dff85394118 *./tests/data/lavf/lavf.wtv
413696 ./tests/data/lavf/lavf.wtv 413696 ./tests/data/lavf/lavf.wtv
./tests/data/lavf/lavf.wtv CRC=0xebced481 ./tests/data/lavf/lavf.wtv CRC=0x133216c1

View File

@ -1,4 +1,4 @@
ret: 0 st: 0 flags:1 dts:-0.040000 pts:-0.040000 pos: 2144 size: 24801 ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 2144 size: 24801
ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st:-1 flags:0 ts:-1.000000
ret: 0 st: 0 flags:1 dts: NOPTS pts: 0.000000 pos: 2144 size: 24801 ret: 0 st: 0 flags:1 dts: NOPTS pts: 0.000000 pos: 2144 size: 24801
ret:-1 st:-1 flags:1 ts: 1.894167 ret:-1 st:-1 flags:1 ts: 1.894167