Conversation
|
|
@LTe I just saw your PR on the ffmpeg repo and ran the fate tests on version 8.1, which is causing some failures. Is this expected? Another question is, how do you plan to probe ffmpeg to see if this fix is included? We do not force users to use jellyfin-ffmpeg in their custom builds, or users may be using an older version of jellyfin-ffmpeg. Therefore, we expect the ffmpeg command-line to be backward compatible. --- ./tests/ref/fate/matroska-avoid-negative-ts 2026-03-17 02:13:05.000000000 +0800
+++ tests/data/fate/matroska-avoid-negative-ts 2026-04-10 18:17:42.192301786 +0800
@@ -1,5 +1,5 @@
-fb4e7a969ef65f61c4c45d5976188aa2 *tests/data/fate/matroska-avoid-negative-ts.matroska
-973080 tests/data/fate/matroska-avoid-negative-ts.matroska
+3718a993550368868eb5d8eb1ca9bb19 *tests/data/fate/matroska-avoid-negative-ts.matroska
+902848 tests/data/fate/matroska-avoid-negative-ts.matroska
#extradata 0: 22, 0x2885037c
#tb 0: 1/1000
#media_type 0: video
@@ -11,31 +11,20 @@
#codec_id 1: mp3
#sample_rate 1: 44100
#channel_layout_name 1: mono
-0, -37, 43, 40, 9156, 0xe5bd034a
-1, 0, 0, 26, 417, 0x7198c15e
-0, 3, 3, 40, 1740, 0x29ac4480, F=0x0
-1, 26, 26, 26, 417, 0x3c67c32d
-0, 43, 123, 40, 3672, 0x98652013, F=0x0
-1, 52, 52, 26, 417, 0x8c24b1ca
-1, 78, 78, 26, 417, 0x6ee576b7
-0, 83, 83, 40, 2532, 0xa2c42769, F=0x0
-1, 104, 104, 26, 417, 0x407603db
-0, 123, 203, 40, 1728, 0xae823d3b, F=0x0
+1, 0, 0, 26, 417, 0x3c67c32d
+1, 26, 26, 26, 417, 0x8c24b1ca
+1, 52, 52, 26, 417, 0x6ee576b7
+1, 78, 78, 26, 417, 0x407603db
+1, 104, 104, 26, 417, 0xcf2804d2
1, 130, 130, 26, 417, 0xcf2804d2
1, 156, 156, 26, 417, 0xcf2804d2
-0, 163, 163, 40, 1028, 0x286ac52a, F=0x0
1, 182, 182, 26, 417, 0xcf2804d2
-0, 203, 283, 40, 1916, 0xd378899e, F=0x0
-1, 208, 208, 26, 417, 0xcf2804d2
+1, 209, 209, 26, 417, 0xcf2804d2
1, 235, 235, 26, 417, 0xcf2804d2
-0, 243, 243, 40, 1168, 0x424e12cf, F=0x0
1, 261, 261, 26, 417, 0xcf2804d2
-0, 283, 363, 40, 1660, 0x5cec156c, F=0x0
-1, 287, 287, 26, 417, 0xcf2804d2
-1, 313, 313, 26, 417, 0xef163d04
-0, 323, 323, 40, 1004, 0xac0dce29, F=0x0
-1, 339, 339, 26, 417, 0x2a009b3a
-0, 363, 443, 40, 3008, 0x0fc798bf, F=0x0
-1, 365, 365, 26, 417, 0xbedccb9d
-1, 365, 365, 26, 417, 0x2214be3f
-1, 391, 391, 26, 417, 0x8953b878
+1, 287, 287, 26, 417, 0xef163d04
+1, 313, 313, 26, 417, 0x2a009b3a
+1, 339, 339, 26, 417, 0xbedccb9d
+1, 339, 339, 26, 417, 0x2214be3f
+1, 365, 365, 26, 417, 0x8953b878
+1, 391, 391, 26, 417, 0x9fcdb36e
Test matroska-avoid-negative-ts failed. Look at tests/data/fate/matroska-avoid-negative-ts.err for details.
make: *** [tests/Makefile:323: fate-matroska-avoid-negative-ts] Error 1
make: *** Waiting for unfinished jobs.... |
Noted, I will prepare patch with quilt |
No this is not expected. I was testing using local generated files. I will try to run full suite with external assets.
In case it will be merged to upstream we can just check version. |
Please run the fate tests as described in the link: https://ffmpeg.org/fate.html In addition, I noticed that the test items here are different from those added in the ffmpeg repo. Is it because they haven't been synchronized yet? |
|
@nyanmisaka The matroska-avoid-negative-ts failure is fixed. The issue was that the threshold adjustment triggered for negative output_ts_offset values too. With output_ts_offset = -60ms, subtracting a negative value raised the discard threshold instead of lowering it, causing valid video packets to be dropped.
The test variable wiring differs because jellyfin-ffmpeg 7.1.3's hlsenc.mak doesn't have the FATE_HLSENC_LAVFI section that upstream 8.x has. The actual test commands, source generation, and reference files are identical. We can add the FATE_HLSENC_LAVFI infrastructure to the quilt patch if you prefer exact parity, but it would mean backporting unrelated upstream test changes. I can also prepare pull request against version 8.0, but then it will be to your repository I think. At least until #664 will be merged. |
00a6477 to
6a1d691
Compare
Let's leave it as it is. I want to keep this open for a while, so we can wait for upstream ffmpeg devs to leave some feedback. Regarding 8.1, you only need to update your PR in the ffmpeg repo, and I will update my branch accordingly once this PR is merged. |
This comment was marked as outdated.
This comment was marked as outdated.
69ee8b3 to
7e15e3d
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Damn, I guess generating content in FATE specs is not really good idea. I guess I will try use ffmpeg samples — this should be consistent. |
Add patch that sets filter ts_offset to 0 and skips start_time subtraction in of_streamcopy() when copy_ts is set. Also fixes check_recording_time() to account for start_time with -copyts. This avoids needing -output_ts_offset or -max_interleave_delta 0, fixing HLS segments missing audio on seeks beyond 10s.
7e15e3d to
ca843e4
Compare
| + int64_t end_time = of->recording_time; | ||
| + | ||
| + if (copy_ts && of->start_time != AV_NOPTS_VALUE) | ||
| + end_time += of->start_time; |
There was a problem hiding this comment.
One thing I'm not very sure if it is correct: do_subtitle_out() does pts -= of->start_time; before calling this helper if the start_time is non zero. Which means the ts being passed in is always 0 based and the end time now will be far beyond the original subtitle end time, if I understand it correctly. Although Jellyfin current does not use subtitle path for this, but current behavior will very likely break that use case and we have a lot of users use jellyfin ffmpeg for general use cases.
There was a problem hiding this comment.
Another problem here is that this addition is not bound checked so we do have potential of signed overflow (although rare). The original logic does the bound check for of->recording_time before av_compare_ts but I think we added another potential of overflow here, because end_time is not only inheriting the recording_time value, it would also add another value on top of it.
There was a problem hiding this comment.
Maybe not that rare, I just realized that without -t, recording_time is intentionally initialized to INT64_MAX, which does cover a huge use case.
|
There is a workaround in user space with drop filter. Therefore custom patch is not needed. There is still a bug but I think it should be fixed in upstream. https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22765#issuecomment-36410 |
Changes
When using
-copytswith output-ss, timestamps are zeroed to ~0 instead ofbeing preserved at the seek position.
Without
-copyts, output-ss 120correctly produces output starting at 0.With
-copytsbut without output-ss, timestamps are correctly preserved at ~120.However,
-copytscombined with output-ss 120incorrectly zeros timestamps to ~0.Root cause
Three places unconditionally subtract
start_timefrom timestamps regardlessof
-copyts:of_streamcopy()subtractsstart_timefrom stream-copied packet timestampsts_offset = start_timeto shift encoded outputback to zero
check_recording_time()in the encoder compares frame PTS againstrecording_timewithout accounting for the preserved timestampsWith
-copyts, the demuxer preserves original timestamps (~120s). Subtractingstart_timezeros them, which is correct without-copyts(where the demuxeralready reset to ~0) but wrong with
-copyts.Fix
Three changes, all gated on
copy_ts:fftools/ffmpeg_mux.c: Skipstart_timesubtraction inof_streamcopy()when
copy_tsis set. Stream-copied packets keep their original PTS.fftools/ffmpeg_mux_init.c: Set filterts_offset = 0whencopy_tsisset. With
-copyts, input frames already carry the real PTS, so the trimfilter sees them directly without a round-trip shift.
fftools/ffmpeg_enc.c: Incheck_recording_time(), compare againstrecording_time + start_timewhencopy_tsis set. This matches the existingstream-copy check at
ffmpeg_mux.c:469and prevents-tfrom stoppingencoding immediately when frame PTS is at the seek position.
Both encoded and stream-copied packets stay at their original PTS throughout the
pipeline, so the interleaver sees no DTS gap between streams.
Tests
8 new FATE tests covering all flag combinations:
HLS tests (
hlsenc.mak, framecrc):fate-streamcopy-extaudio-nocopyts:-output_ts_offsetwithout-copytsfate-streamcopy-extaudio-plain: output-ssonlyfate-streamcopy-extaudio-partial-offset: partial-output_ts_offsetfate-streamcopy-extaudio-copyts:-copytswith output-ssfate-streamcopy-extaudio-copyts-interleave: 30s seek with-copytsEncoder tests (
enc-copyts.mak, transcode md5+framecrc):fate-enc-copyts-mpeg4-ss: input-ssonlyfate-enc-copyts-mpeg4-ss-copyts: input-ss+-copytsfate-enc-copyts-mpeg4-ss-outss-copyts-offset: explicit-output_ts_offsetAll tests use built-in encoders only (mpeg4, mp2fixed). Full FATE suite
passes with
--assert-level=2.Issues
https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22765
jellyfin/jellyfin#16580