This PR depends on newer ffmpeg API features (copying user-supplied opaque data from frame to pkt) so the changes will have to be merged alongside the ffmpeg upgrade itself - #406. Posting a PR here so the details of the fix are more easily accessible as a historical reference
Set the encoder timebase using AVCodecContext.framerate instead of the decoder's AVCodecContext.time_base.
Adjust the packet timebase as necessary for FPS pass through to match the encoder's expected timebase. For filtergraphs using FPS adjustment, the filtergraph output timebase will match the framerate (1 / framerate) and the encoder is configured for the same.
However, for FPS pass through, the filtergraph's output timebase will match the input timebase (since there is no FPS adjustment) while the encoder uses the timebase detected from the decoder's framerate. Since the input timebase does not typically match the FPS (eg 90khz for mpegts vs 30fps), we need to adjust the packet timestamps (in container timebase) to the encoder's expected timebase.
For the specific case of FPS passthrough, preserve the original PTS as much as possible since we are trying to re-encode existing frames one-to-one. Use the opaque field for this, since it is already being populated with the original PTS to detect sentinel packets during flushing.
Without this, timestamps can be slightly "squashed" down when rescaling output packets to the muxer's timebase, due to the loss of precision (eg, demuxer 90khz -> encoder 30hz -> muxer 90khz)
Do not merge
This PR depends on newer ffmpeg API features (copying user-supplied opaque data from frame to pkt) so the changes will have to be merged alongside the ffmpeg upgrade itself - #406. Posting a PR here so the details of the fix are more easily accessible as a historical reference
Set the encoder timebase using AVCodecContext.framerate instead of the decoder's AVCodecContext.time_base.
The use of AVCodecContext.time_base is deprecated for decoding. See https://ffmpeg.org/doxygen/3.3/structAVCodecContext.html#ab7bfeb9fa5840aac090e2b0bd0ef7589
Adjust the packet timebase as necessary for FPS pass through to match the encoder's expected timebase. For filtergraphs using FPS adjustment, the filtergraph output timebase will match the framerate (1 / framerate) and the encoder is configured for the same.
However, for FPS pass through, the filtergraph's output timebase will match the input timebase (since there is no FPS adjustment) while the encoder uses the timebase detected from the decoder's framerate. Since the input timebase does not typically match the FPS (eg 90khz for mpegts vs 30fps), we need to adjust the packet timestamps (in container timebase) to the encoder's expected timebase.
For the specific case of FPS passthrough, preserve the original PTS as much as possible since we are trying to re-encode existing frames one-to-one. Use the opaque field for this, since it is already being populated with the original PTS to detect sentinel packets during flushing.
Without this, timestamps can be slightly "squashed" down when rescaling output packets to the muxer's timebase, due to the loss of precision (eg, demuxer 90khz -> encoder 30hz -> muxer 90khz)