-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix FPS passthrough #405
Closed
Closed
Fix FPS passthrough #405
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* 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)
Incorporated in #406 |
j0sh
added a commit
that referenced
this pull request
Aug 9, 2024
The DTS from the encoder can be "squashed" a bit during rescaling if used directly due to the lower resolution of the encoder timebase, so take the difference between the encoder-provided dts/pts, rescale that difference and incorporate that into the original pts. The main thing this does is to ensure that non-B frames have the same dts/pts. Also see #405
j0sh
added a commit
that referenced
this pull request
Aug 10, 2024
This mostly ensures that non-B frames have the same dts/pts. The PTS/DTS from the encoder can be "squashed" a bit during rescaling back to the source timebase if it is used directly, due to the lower resolution of the encoder timebase. We avoid this problem with the PTS in in FPS passthrough mode by reusing the source pts, but only rescale the encoder-provided DTS back to the source timebase for some semblance of timestamp consistency. Because the DTS values are squashed, they can differ from the PTS even with non-B frames. The DTS values are still monotonic, so the exact numbers are not really important. However, some tools use `dts == pts` as a heuristic to check for B-frames ... so help them out to avoid spurious B-frame detections. To fix the DTS/PTS mismatch, take the difference between the encoder-provided dts/pts, rescale that difference back to the source time base, and re-calculate the dts using the source pts. Also see #405
thomshutt
pushed a commit
that referenced
this pull request
Aug 12, 2024
This mostly ensures that non-B frames have the same dts/pts. The PTS/DTS from the encoder can be "squashed" a bit during rescaling back to the source timebase if it is used directly, due to the lower resolution of the encoder timebase. We avoid this problem with the PTS in in FPS passthrough mode by reusing the source pts, but only rescale the encoder-provided DTS back to the source timebase for some semblance of timestamp consistency. Because the DTS values are squashed, they can differ from the PTS even with non-B frames. The DTS values are still monotonic, so the exact numbers are not really important. However, some tools use `dts == pts` as a heuristic to check for B-frames ... so help them out to avoid spurious B-frame detections. To fix the DTS/PTS mismatch, take the difference between the encoder-provided dts/pts, rescale that difference back to the source time base, and re-calculate the dts using the source pts. Also see #405
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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)