mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-27 13:30:45 +00:00
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:
parent
d07de6d75d
commit
ad53c7f9ec
1
ffmpeg.c
1
ffmpeg.c
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user