Line 481 of /ffpyplayer/writer.pyx is as follows:
rounded_pts = <int64_t>floor(pts / av_q2d(s.codec_ctx.time_base) + 0.5)
This works correctly if time_base is (X,1) for any X, but not for timebases with denominator other than 1.
Specifically, i want to write a file with fps = 24.9069 Hz. That means in the opts dict for the stream i set frame_rate:(244212,9805), which is a close approximation with a reasonable denominator. If i then feed in exactly frame_number/fps as pts into write_frame things work ok, but as soon as i have some jitter on my frame timestamps, things collapse because the above line may well lead to two consecutive frames with the same rounded_pts, which causes Error writing packet: Invalid argument with h264 into a mp4 container.
More generally, an AVFrame's pts should be in time_base units (ffmpeg code says pts is Presentation timestamp in time_base units (time when frame should be shown to user)), and the above code only does that when timebase has a denominator of 1, but not otherwise. I think the line should be:
rounded_pts = <int64_t>floor(pts*s.codec_ctx.time_base.den + 0.5) (which is equivalent to rounded_pts = <int64_t>floor(pts / av_q2d(s.codec_ctx.time_base)*s.codec_ctx.time_base.num + 0.5)), but am not able to test this myself.
Calculation example: I have some frames with the following pts (in seconds): [0., 0.04014954222907545, 0.0802990844581509, 0.10583208445814671, 0.12895308445813133, 0.14478608445817373]. That is VFR. With my timebase of num 9805, den 244212 (i.e. av_q2d returns 0.040149542201038), the above code gives these frames pts:
Line 481 of /ffpyplayer/writer.pyx is as follows:
rounded_pts = <int64_t>floor(pts / av_q2d(s.codec_ctx.time_base) + 0.5)
This works correctly if time_base is (X,1) for any X, but not for timebases with denominator other than 1. Specifically, i want to write a file with fps = 24.9069 Hz. That means in the opts dict for the stream i set
frame_rate:(244212,9805)
, which is a close approximation with a reasonable denominator. If i then feed in exactly frame_number/fps as pts into write_frame things work ok, but as soon as i have some jitter on my frame timestamps, things collapse because the above line may well lead to two consecutive frames with the same rounded_pts, which causesError writing packet: Invalid argument
with h264 into a mp4 container.More generally, an AVFrame's pts should be in time_base units (ffmpeg code says pts is
Presentation timestamp in time_base units (time when frame should be shown to user)
), and the above code only does that when timebase has a denominator of 1, but not otherwise. I think the line should be:rounded_pts = <int64_t>floor(pts*s.codec_ctx.time_base.den + 0.5)
(which is equivalent torounded_pts = <int64_t>floor(pts / av_q2d(s.codec_ctx.time_base)*s.codec_ctx.time_base.num + 0.5)
), but am not able to test this myself.Calculation example: I have some frames with the following pts (in seconds): [0., 0.04014954222907545, 0.0802990844581509, 0.10583208445814671, 0.12895308445813133, 0.14478608445817373]. That is VFR. With my timebase of num 9805, den 244212 (i.e. av_q2d returns 0.040149542201038), the above code gives these frames pts:
where they should be:
which is what is yielded byfloor(pts*s.codec_ctx.time_base.den + 0.5).