mirror of https://github.com/mpv-player/mpv
video: warn user against FFmpeg's lies
I found that at least for mjpeg streams, FFmpeg will set packet pts/dts anyway. The mjpeg raw video demuxer (along with some other raw formats) has a "framerate" demuxer option which defaults to 25, so all mjpeg streams will be played at 25 FPS by default. mpv doesn't like this much. If AVFMT_NOTIMESTAMPS is set, it prints a warning, that might print a bogus FPS value for the assumed framerate. The code was originally written with the assumption that FFmpeg would not set pts/dts for such formats, but since it does, the printed estimated framerate will never be used. --fps will also not be used by default in this situation. To make this hopefully less confusing, explicitly state the situation when the AVFMT_NOTIMESTAMPS flag is set, and give instructions how to work it around. Also, remove the warning in dec_video.c. We don't know what FPS it's going to assume anyway. If there are really no timestamps in the stream, it will trigger our normal missing pts workaround. Add the assumed FPS there. In theory, we could just clear packet timestamps if AVFMT_NOTIMESTAMPS is set, and make up our own timestamps. That is non-trivial for advanced video codecs like h264, so I'm not going there. For seeking and buffering estimation the situation thus remains half-broken. This is a mitigation for #5419.
This commit is contained in:
parent
70b2be3cf7
commit
c88ab96a78
|
@ -940,6 +940,19 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
|
|||
demuxer->duration = duration;
|
||||
}
|
||||
|
||||
// In some cases, libavformat will export bogus bullshit timestamps anyway,
|
||||
// such as with mjpeg.
|
||||
if (priv->avif_flags & AVFMT_NOTIMESTAMPS) {
|
||||
MP_WARN(demuxer,
|
||||
"This format is marked by FFmpeg as having no timestamps!\n"
|
||||
"FFmpeg will likely make up its own broken timestamps. For\n"
|
||||
"video streams you can correct this with:\n"
|
||||
" --no-correct-pts --fps=VALUE\n"
|
||||
"with VALUE being the real framerate of the stream. You can\n"
|
||||
"expect seeking and buffering estimation to be generally\n"
|
||||
"broken as well.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,12 +175,6 @@ bool video_init_best_codec(struct dec_video *d_video)
|
|||
d_video->codec->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;
|
||||
}
|
||||
|
@ -333,16 +327,19 @@ static bool receive_frame(struct dec_video *d_video, struct mp_image **out_image
|
|||
pts = dts;
|
||||
|
||||
if (!opts->correct_pts || pts == MP_NOPTS_VALUE) {
|
||||
if (opts->correct_pts && !d_video->header->missing_timestamps) {
|
||||
double fps = d_video->fps > 0 ? d_video->fps : 25;
|
||||
|
||||
if (opts->correct_pts) {
|
||||
if (d_video->has_broken_decoded_pts <= 1) {
|
||||
MP_WARN(d_video, "No video PTS! Making something up.\n");
|
||||
MP_WARN(d_video, "No video PTS! Making something up. using "
|
||||
"%f FPS.\n", fps);
|
||||
if (d_video->has_broken_decoded_pts == 1)
|
||||
MP_WARN(d_video, "Ignoring further missing PTS warnings.\n");
|
||||
d_video->has_broken_decoded_pts++;
|
||||
}
|
||||
}
|
||||
|
||||
double frame_time = 1.0f / (d_video->fps > 0 ? d_video->fps : 25);
|
||||
double frame_time = 1.0f / fps;
|
||||
double base = d_video->first_packet_pdts;
|
||||
pts = d_video->decoded_pts;
|
||||
if (pts == MP_NOPTS_VALUE) {
|
||||
|
|
Loading…
Reference in New Issue