mirror of
https://github.com/mpv-player/mpv
synced 2024-12-25 08:12:17 +00:00
video: add insane hack to work around FFmpeg/Libav insanity
So, FFmpeg/Libav requires us to figure out video timestamps ourselves (see last 10 commits or so), but the methods it provides for this aren't even sufficient. In particular, everything that uses AVI-style DTS (avi, vfw-muxed mkv, possibly mpeg4-in-ogm) with a codec that has an internal frame delay is broken. In this case, libavcodec will shift the packet- to-image correspondence by the codec delay, meaning that with a delay=1, the first AVFrame.pkt_dts is not 0, but that of the second packet. All timestamps will appear shifted. The start time (e.g. the time displayed when doing "mpv file.avi --pause") will not be exactly 0. (According to Libav developers, this is how it's supposed to work; just that the first DTS values are normally negative with formats that use DTS "properly". Who cares if it doesn't work at all with very common video formats? There's no indication that they'll fix this soon, either. An elegant workaround is missing too.) Add a hack to re-enable the old PTS code for AVI and vfw-muxed MKV. Since these timestamps are not reorderd, we wouldn't need to sort them, but it's less code this way (and possibly more robust, should a demuxer unexpectedly output PTS). The original intention of all the timestamp changes recently was actually to get rid of demuxer-specific hacks and the old timestamp sorting code, but it looks like this didn't work out. Yet another case where trying to replace native MPlayer functionality with FFmpeg/Libav led to disadvantages and bugs. (Note that the old PTS sorting code doesn't and can't handle frame dropping correctly, though.) Bug reports: https://trac.ffmpeg.org/ticket/3178 https://bugzilla.libav.org/show_bug.cgi?id=600
This commit is contained in:
parent
d9b5dedfe9
commit
dc0b2046cd
@ -441,6 +441,9 @@ static void handle_stream(demuxer_t *demuxer, int i)
|
||||
/ (float)(codec->height * codec->sample_aspect_ratio.den);
|
||||
sh_video->i_bps = codec->bit_rate / 8;
|
||||
|
||||
// This also applies to vfw-muxed mkv, but we can't detect these easily.
|
||||
sh_video->avi_dts = matches_avinputformat_name(priv, "avi");
|
||||
|
||||
mp_msg(MSGT_DEMUX, MSGL_DBG2, "aspect= %d*%d/(%d*%d)\n",
|
||||
codec->width, codec->sample_aspect_ratio.num,
|
||||
codec->height, codec->sample_aspect_ratio.den);
|
||||
|
@ -1338,6 +1338,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
|
||||
sh_v->disp_h = track->v_dheight;
|
||||
}
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Aspect: %f\n", sh_v->aspect);
|
||||
sh_v->avi_dts = track->ms_compat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ typedef struct sh_audio {
|
||||
} sh_audio_t;
|
||||
|
||||
typedef struct sh_video {
|
||||
bool avi_dts; // use DTS timing; first frame and DTS is 0
|
||||
float fps; // frames per second (set only if constant fps)
|
||||
float aspect; // aspect ratio stored in the file (for prescaling)
|
||||
int i_bps; // == bitrate (compressed bytes/sec)
|
||||
|
@ -262,9 +262,12 @@ static double retrieve_sorted_pts(struct dec_video *d_video, double codec_pts)
|
||||
d_video->num_unsorted_pts_problems++;
|
||||
d_video->unsorted_pts = codec_pts;
|
||||
|
||||
if (opts->user_pts_assoc_mode)
|
||||
if (d_video->header->video->avi_dts) {
|
||||
// Actually, they don't need to be sorted, we just reuse the buffering.
|
||||
d_video->pts_assoc_mode = 2;
|
||||
} else if (opts->user_pts_assoc_mode) {
|
||||
d_video->pts_assoc_mode = opts->user_pts_assoc_mode;
|
||||
else if (d_video->pts_assoc_mode == 0) {
|
||||
} else if (d_video->pts_assoc_mode == 0) {
|
||||
if (codec_pts != MP_NOPTS_VALUE)
|
||||
d_video->pts_assoc_mode = 1;
|
||||
else
|
||||
@ -292,7 +295,9 @@ struct mp_image *video_decode(struct dec_video *d_video,
|
||||
int drop_frame)
|
||||
{
|
||||
struct MPOpts *opts = d_video->opts;
|
||||
bool sort_pts = opts->user_pts_assoc_mode != 1 && opts->correct_pts;
|
||||
bool sort_pts =
|
||||
(opts->user_pts_assoc_mode != 1 || d_video->header->video->avi_dts)
|
||||
&& opts->correct_pts;
|
||||
double pkt_pts = packet ? packet->pts : MP_NOPTS_VALUE;
|
||||
double pkt_dts = packet ? packet->dts : MP_NOPTS_VALUE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user