From fe0c37b00715e17d84b524b0f6f57d910a82806d Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 20 Mar 2015 22:07:26 +0100 Subject: player: better handling of video with no timestamps Trying to handle such video is almost worthless, but it was requested by at least 2 users. If there are no timestamps, enable byte seeking by setting ts_resets_possible. Use the video FPS (wherever it comes from) and the audio samplerate for timing. The latter was already done by making the first packet emit DTS=0; remove this again and do it "properly" in a higher level. --- audio/decode/dec_audio.c | 3 +++ demux/demux_lavf.c | 13 +++---------- demux/stheader.h | 2 ++ video/decode/dec_video.c | 8 +++++++- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index ab4cd2ec55..c5ad97f7af 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -164,6 +164,9 @@ static int decode_new_frame(struct dec_audio *da) if (ret < 0) return ret; + if (da->pts == MP_NOPTS_VALUE && da->header->missing_timestamps) + da->pts = 0; + if (da->waiting) { da->pts_offset += da->waiting->samples; da->decode_format = *da->waiting; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 0275b1afd2..2799dd33f9 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -151,7 +151,6 @@ typedef struct lavf_priv { AVFormatContext *avfc; AVIOContext *pb; int64_t last_pts; - bool init_pts; struct sh_stream **streams; // NULL for unknown streams int num_streams; int cur_program; @@ -618,6 +617,7 @@ static void handle_stream(demuxer_t *demuxer, int i) sh->hls_bitrate = dict_get_decimal(st->metadata, "variant_bitrate", 0); if (!sh->title && sh->hls_bitrate > 0) sh->title = talloc_asprintf(sh, "bitrate %d", sh->hls_bitrate); + sh->missing_timestamps = !!(priv->avif->flags & AVFMT_NOTIMESTAMPS); } select_tracks(demuxer, i); @@ -794,7 +794,8 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) mp_tags_copy_from_av_dictionary(demuxer->metadata, avfc->metadata); update_metadata(demuxer, NULL); - demuxer->ts_resets_possible = priv->avif->flags & AVFMT_TS_DISCONT; + demuxer->ts_resets_possible = + priv->avif->flags & (AVFMT_TS_DISCONT | AVFMT_NOTIMESTAMPS); demuxer->start_time = priv->avfc->start_time == AV_NOPTS_VALUE ? 0 : (double)priv->avfc->start_time / AV_TIME_BASE; @@ -839,12 +840,6 @@ static int demux_lavf_fill_buffer(demuxer_t *demux) return 1; } - if (!priv->init_pts && (priv->avfc->flags & AVFMT_NOTIMESTAMPS)) { - if (pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE) - pkt->dts = 0; - priv->init_pts = true; - } - if (pkt->pts != AV_NOPTS_VALUE) dp->pts = pkt->pts * av_q2d(st->time_base); if (pkt->dts != AV_NOPTS_VALUE) @@ -873,8 +868,6 @@ static void demux_seek_lavf(demuxer_t *demuxer, double rel_seek_secs, int flags) lavf_priv_t *priv = demuxer->priv; int avsflags = 0; - priv->init_pts = false; - if (flags & SEEK_ABSOLUTE) priv->last_pts = 0; else if (rel_seek_secs < 0) diff --git a/demux/stheader.h b/demux/stheader.h index fbfba01367..1af91e032b 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -58,6 +58,8 @@ struct sh_stream { bool default_track; // container default track flag int hls_bitrate; + bool missing_timestamps; + // stream is a picture (such as album art) struct demux_packet *attached_picture; diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index a0bd6cb047..c578ccadcc 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -200,6 +200,12 @@ bool video_init_best_codec(struct dec_video *d_video, char* video_decoders) d_video->header->codec ? d_video->header->codec : ""); } + if (d_video->header->missing_timestamps) { + MP_WARN(d_video, "This stream has no timestamps!\n"); + MP_WARN(d_video, "Making up playback time using %f FPS.\n", d_video->fps); + MP_WARN(d_video, "Seeking will probably fail badly.\n"); + } + talloc_free(list); return !!d_video->vd_driver; } @@ -351,7 +357,7 @@ struct mp_image *video_decode(struct dec_video *d_video, pts = retrieve_sorted_pts(d_video, pts); if (!opts->correct_pts || pts == MP_NOPTS_VALUE) { - if (opts->correct_pts) + if (opts->correct_pts && !d_video->header->missing_timestamps) MP_WARN(d_video, "No video PTS! Making something up.\n"); double frame_time = 1.0f / (d_video->fps > 0 ? d_video->fps : 25); -- cgit v1.2.3