deps-libff: Offset start of stream by start pts
Now that we're using the timestamps from the stream for playback, certain types of streams and certain file formats will not start from a pts of 0. This causes the start of the playback to be delayed. This code simply ensures that there's no delay on startup. This is basically the same code as used in FFmpeg itself for handling this situation.master
parent
4725641c88
commit
171f0e3d26
|
@ -50,6 +50,7 @@ struct ff_decoder *ff_decoder_init(AVCodecContext *codec_context,
|
|||
decoder->timer_next_wake = (double)av_gettime() / 1000000.0;
|
||||
decoder->previous_pts_diff = 40e-3;
|
||||
decoder->current_pts_time = av_gettime();
|
||||
decoder->start_pts = 0;
|
||||
decoder->predicted_pts = 0;
|
||||
|
||||
success = ff_timer_init(&decoder->refresh_timer, ff_decoder_refresh,
|
||||
|
@ -308,6 +309,8 @@ double ff_decoder_get_best_effort_pts(struct ff_decoder *decoder,
|
|||
best_effort_pts = av_frame_get_best_effort_timestamp(frame);
|
||||
|
||||
if (best_effort_pts != AV_NOPTS_VALUE) {
|
||||
best_effort_pts -= decoder->start_pts;
|
||||
|
||||
// Since the best effort pts came from the stream we use his
|
||||
// time base
|
||||
d_pts = best_effort_pts * av_q2d(decoder->stream->time_base);
|
||||
|
|
|
@ -46,6 +46,7 @@ struct ff_decoder {
|
|||
double predicted_pts; // predicted pts of next frame
|
||||
double current_pts; // pts of the most recently dispatched frame
|
||||
int64_t current_pts_time; // clock time when current_pts was set
|
||||
int64_t start_pts;
|
||||
|
||||
bool hwaccel_decoder;
|
||||
enum AVDiscard frame_drop;
|
||||
|
|
|
@ -380,12 +380,21 @@ static bool open_input(struct ff_demuxer *demuxer,
|
|||
return avformat_find_stream_info(*format_context, NULL) >= 0;
|
||||
}
|
||||
|
||||
static inline void set_decoder_start_time(struct ff_decoder *decoder,
|
||||
int64_t start_time)
|
||||
{
|
||||
if (decoder)
|
||||
decoder->start_pts = av_rescale_q(start_time, AV_TIME_BASE_Q,
|
||||
decoder->stream->time_base);
|
||||
}
|
||||
|
||||
static bool find_and_initialize_stream_decoders(struct ff_demuxer *demuxer)
|
||||
{
|
||||
AVFormatContext *format_context = demuxer->format_context;
|
||||
unsigned int i;
|
||||
AVStream *audio_stream = NULL;
|
||||
AVStream *video_stream = NULL;
|
||||
int64_t start_time = INT64_MAX;
|
||||
|
||||
for (i = 0; i < format_context->nb_streams; i++) {
|
||||
AVCodecContext *codec = format_context->streams[i]->codec;
|
||||
|
@ -424,6 +433,32 @@ static bool find_and_initialize_stream_decoders(struct ff_demuxer *demuxer)
|
|||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < format_context->nb_streams; i++) {
|
||||
AVStream *st = format_context->streams[i];
|
||||
int64_t st_start_time;
|
||||
|
||||
if (st->discard == AVDISCARD_ALL ||
|
||||
st->start_time == AV_NOPTS_VALUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
st_start_time = av_rescale_q(st->start_time, st->time_base,
|
||||
AV_TIME_BASE_Q);
|
||||
start_time = FFMIN(start_time, st_start_time);
|
||||
}
|
||||
|
||||
if (format_context->start_time != AV_NOPTS_VALUE) {
|
||||
if (start_time > format_context->start_time ||
|
||||
start_time == INT64_MAX) {
|
||||
start_time = format_context->start_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (start_time != INT64_MAX) {
|
||||
set_decoder_start_time(demuxer->video_decoder, start_time);
|
||||
set_decoder_start_time(demuxer->audio_decoder, start_time);
|
||||
}
|
||||
|
||||
if (demuxer->audio_decoder != NULL) {
|
||||
if (ff_callbacks_initialize(&demuxer->audio_callbacks)) {
|
||||
ff_decoder_start(demuxer->audio_decoder);
|
||||
|
|
Loading…
Reference in New Issue