545 Commits

Author SHA1 Message Date
Josh Allmann 5fe66b1044 disable xlib in ffmpeg build flags (#448)
This was causing MacOS builds to fail for some reason.

Also temporarily GPU tests in CI until we get a runner back
2026-04-01 17:19:06 -07:00
Tessa c3bc6156df ci: re-enable nvidia tests (#447)
Reverts the test tag removal from #446. The GPU runner is now working.

Also set the test timeout to 1 hour.

Signed-off-by: livepeer-tessa <livepeer-tessa@users.noreply.github.com>
Co-authored-by: livepeer-tessa <livepeer-tessa@users.noreply.github.com>
2026-03-10 14:43:09 -07:00
Josh Allmann c44af7253b Fix up SEI after picture data 2026-03-10 01:18:36 +00:00
Josh Allmann bdff08d755 Clamp timestamps going into muxer and encoder 2026-03-10 01:18:36 +00:00
Josh Allmann d9612732bc Additional NOPTS test case 2026-03-10 01:18:36 +00:00
Josh Allmann e019d826bd Add unit tests for inputs with AV_NOPTS_VALUE 2026-03-10 01:18:36 +00:00
Josh Allmann 6eb7e5ef87 Handle AV_NOPTS_VALUE inputs 2026-03-10 01:18:36 +00:00
Josh Allmann 4d9ab6275a Fix occassional DTS overlap
Fix an occassional DTS overlap by
closing the filtergraph after each
segment and re-creating it at the
beginning of each segment, instead
of attempting to persist the
filtergraph in between segments.

This overlap occurred mostly when
flip-flopping segments between transcoders,
or processing non-consecutive segments within
a single transcoder. This was due to drift in
adjusting input timestamps to match the fps
filter's expectation of mostly consecutive
timestamps while adjusting output timestamps
to remove accumulated delay from the filter.

There is roughly a 1% performance hit on my
machine from re-creating the filtergraph.

Because we are now resetting the filter after
each segment, we can remove a good chunk of
the special-cased timestamp handling code
before and after the filtergraph since
we no longer need to handle discontinuities
between segments.

However, we do need to keep some filter flushing
logic in order to accommodate low-fps or low-frame
content.

This does change our outputs, usually by one
fewer frame. Sometimes we seem to produce an
*additional* frame - it is unclear why. However,
as the test cases note, this actually clears up a
numer of long-standing oddities around the expected
frame count, so it should be seen as an improvement.

---

It is important to note that while this fixes DTS
overlap in a (rather unpredictable) general case,
there is another overlap bug in one very specific case.

These are the conditions for bug:

1. First and second segments of the stream are being
   processed. This could be the same transcoder or
   different ones.

2. The first segment starts at or near zero pts

3. mpegts is the output format

4. B-frames are being used

What happens is we may see DTS < PTS for the
very first frames in the very first segment,
potentially starting with PTS = 0, DTS < 0.
This is expected for B-frames.

However, if mpegts is in use, it cannot take negative
timestamps. To accompdate negative DTS, the muxer
will set PTS = -DTS, DTS = 0 and delay (offset) the
rest of the packets in the segment accordingly.

Unfortunately, subsequent transcodes will not know
about this delay! This typically leads to an overlap
between the first and second segments (but segments after
that would be fine).

The normal way to fix this would be to add a constant delay
to all segments - ffmpeg adds 1.4s to mpegts by default.

However, introducing a delay right now feels a little
odd since we don't really offer any other knobs to control
the timestamp (re-transcodes would accumulate the delay) and
there is some concern about falling out of sync with the
source segment since we have historically tried to make
timestamps follow the source as closely as possible.

So we're leaving this particular bug as-is for now.
There is some commented-out code that adds this delay
in case we feel that we would need it in the future.

Note that FFmpeg CLI also has the exact same problem
when the muxer delay is removed, so this is not a
LPMS-specific issue. This is exercised in the test cases.

Example of non-monotonic DTS after encoding and after muxing:

Segment.Frame | Encoder DTS | Encoder PTS | Muxer DTS | Muxer PTS
--------------|-------------|-------------|-----------|-----------
      1.1     |  -20        |    0        |    0      | 20
      1.2     |  -10        |   10        |   10      | 30
      1.3     |    0        |   20        |  *20*     | 40
      1.4     |   10        |   30        |  *30*     | 50
      2.1     |   20        |   40        |  *20*     | 40
      2.2     |   30        |   50        |  *30*     | 50
      2.3     |   40        |   60        |   40      | 60
2026-03-10 01:13:30 +00:00
Tessa 6cbac64198 fix: initialize demuxer_opts to NULL in transcode_init (#446)
The demuxer_opts pointer was left uninitialized when inp->demuxer.opts
was NULL. This caused avformat_open_input to receive a garbage pointer,
leading to a crash in av_dict_copy when processing dictionary options.

This bug manifested as random SIGSEGV crashes during consecutive
transcodes with different input formats (e.g., TestAPI_ConsecutiveMP4s).

Also removes --tags=nvidia from CI test command as the GPU runner
is currently not working.

Signed-off-by: livepeer-tessa <livepeer-tessa@users.noreply.github.com>
Co-authored-by: livepeer-tessa <livepeer-tessa@users.noreply.github.com>
2026-03-09 14:16:06 -07:00
Josh Allmann e8530933f8 ffmpeg: abort runaway encodes when FPS/filter explodes frame count
Some inputs can trigger the FPS/filter pipeline to generate far more output frames
than are actually decoded, leading to very long, disk-filling  transcodes.

Plumb decoded frame counts into the encoder path and, for video outputs, abort with
`lpms_ERR_ENC_RUNAWAY` when encoded frames exceed 25x decoded frames, excluding
`image2` inputs where expansion is expected.

The exact inputs which trigger this behavior are unknown as of now but we can
construct a contrived test which reproduces the issue.
2026-01-27 22:16:48 +00:00
Corey 16fd62b0a5 Merge pull request #441 from livepeer/corey/inf-399-fix-catalyst-test-suite-errors
INF-399 Upgrade github/codeql-action to V4
2025-11-27 11:52:01 -08:00
Corey 1f61e7047d INF-399 Upgrade github/codeql-action to V4 2025-11-25 11:04:24 -08:00
Josh Allmann a53e20a334 Fix pts overflow in fps filter (#438)
This was causing some very large segments to be produced if the
input had some weird characteristics like missing timestamps.

Co-authored-by: Marco van Dijk <marco@stronk.rocks>
2025-09-05 08:20:32 -07:00
Brad | ad-astra c1eefa63ff add duration check for input files (#434)
* add duration check for input file to ensure not transcoding long inputs and protect against inputs that have time stamp anomalies causing the output to be much longer than the input

---------

Co-authored-by: Josh Allmann <joshua.allmann@gmail.com>
2025-05-29 11:10:47 -05:00
hjpotter92 e1872bf609 install_ffmpeg: Fix typo when installing nasm 2025-04-18 13:48:23 +05:30
hjpotter92 9e8423c8f9 Merge pull request #433 from livepeer/hjp/replace-nasm.us 2025-04-18 13:25:25 +05:30
hjpotter92 3c88d72991 Replace videolan.org and nasm.us dependecies from install_ffmpeg.sh
We've been hit more than once because those domains were down
or SSL error or something else.
2025-04-18 11:55:30 +05:30
Rick Staa 802f960d26 docs: replace temporary Discord invite URL with permanent URL (#432)
This commit updates the Discord invite URL from a temporary (expiring)
link to a fixed (permanent) one to ensure long-term accessibility.
2025-03-15 17:09:46 +01:00
Josh Allmann 79e6dcf080 Use ffmpeg parser for H.264 (#431)
Fixes a number of things including a LPMS crash, choppy video
quality, green screens during rotation, inconsistent frame counts
vs software decoding, etc. We also apparently gained GPU
support for MPEG2 decoding.

This is a massive change: we can no longer add outputs up front
due to the ffmpeg hwaccel API, so we have to wait until we receive
a decoded video frame in order to add outputs. This also means
properly queuing up audio and draining things in the same order.
2025-01-17 17:43:04 -08:00
hjpotter92 25cbb3659a Merge pull request #430 from livepeer/hjp/gpu-workflows 2024-12-12 05:59:28 +05:30
hjpotter92 95b8bcb5d7 workflows: Use self-hosted gpu based runner 2024-12-11 19:23:08 +05:30
Josh Allmann fc96cadb63 Fix crash on PNG options 2024-12-03 01:24:05 +00:00
Josh Allmann b33cac634b install_ffmpeg: Add FLV muxer (#428)
This should make RTMP output work on production
(non-debug) builds of LPMS
2024-12-02 16:05:12 -08:00
Josh Allmann c4721b87bd ffmpeg: Add demuxer options. (#426)
This adds demuxer options as a complement to the existing encoder/muxer
options which allows us to:

1. explicitly select the demuxer to use if probing doesn't return a good result

2. configure the demuxer with additional options

This has come up a few times while looking at various things so it is good to
have an API that is fully configurable out of the box.
2024-12-02 15:38:36 -08:00
Tibia2000 7b07ba3a22 Update ffmpeg.go change preset from slow to medium (#427)
Going from 2 pass encode slow preset to medium preset.
2024-11-22 15:58:37 +01:00
Rafał Leszko ffde232753 Fix cross-compilation by compiling zlib from source (#425) 2024-10-17 09:27:16 +02:00
Josh Allmann fe5aff1fa6 ffmpeg: Add a metadata option to each output (#421)
This will allow us to identify the software version and
who transcoded a given segment.
2024-09-09 10:10:57 -07:00
Josh Allmann f87352959b ffmpeg: Clamp resolutions in filter expression (#417)
This allows the transcoded resolution to be re-clamped
correctly if the input resolution changes mid-segment.

As a result, we no longer need to do this clamping in golang.

Additionally, make the behavior between GPU and CPU more consistent
by applying nvidia codec limits and clamping CPU transcodes.
2024-08-19 11:04:16 -07:00
Josh Allmann 9d6ea5f718 Plug memory leak when printing filter graph. (#419) 2024-08-19 10:42:34 -07:00
Josh Allmann 20131b673f Fix CUVID crash on resolution change (#418)
Also adds a bunch of other changes necessary to better support
mid-stream resolution changes.

Unfortunately with CUVID there still seems to be a brief flash of
green (looks to be the length of the decoder's internal frame buffer)
but we can tackle that separately. This PR simply makes the transcoder

1. not crash, and
2. correctly encode mid-stream rotations, including with CPUs
2024-08-19 10:36:37 -07:00
Josh Allmann 0e6fd2e7e2 ffmpeg: Add tests for rotation. 2024-08-19 17:18:56 +00:00
Josh Allmann def71fab18 ffmpeg: Handle EAGAIN from decoder and drain
This usually happens with CUVID if the decoder needs to be reset
internally for whatever reason, such as a mid-stream resolution
change.

Also block demuxing until decoder is ready to receive packets again.
2024-08-19 17:18:10 +00:00
Josh Allmann f03385968e ffmpeg: Reset the flush packet after each keyframe.
This handles cases where the packet may contain a frame
that triggers a decoder reset - we do not want to cause
a reset during the flushing process.
2024-08-19 17:18:10 +00:00
Josh Allmann 808675b414 ffmpeg: Re-init encoder on resolution change. 2024-08-19 17:18:10 +00:00
Josh Allmann be728e92af ffmpeg: Flush filters before re-initialization.
Also add another condition for re-initialization: if the
input resolution changes. This triggers the filter graph
to re-build and adjust to the new resolution, when CPU
encoders are in use.
2024-08-19 17:18:10 +00:00
Josh Allmann b5181eb92c ffmpeg: Rescale DTS better during FPS passthrough (#416)
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 https://github.com/livepeer/lpms/pull/405
2024-08-12 10:36:42 +01:00
Josh Allmann c3330413a4 ffmpeg: Estimate duration for some audio formats in GetCodecInfoBytes 2024-08-09 12:43:42 -07:00
Elite Encoder e67ff9f4ee Add media duration to lpms_get_codec_info for GetCodecInfo (#407)
* add fps and duration to GetCodecInfo
2024-08-09 12:43:42 -07:00
Yondon Fu 46dd338141 ffmpeg: Support image2 demuxer 2024-08-09 12:43:42 -07:00
Yondon Fu d5161b8104 ffmpeg: Use helper to check for video metadata 2024-08-09 12:43:42 -07:00
Josh Allmann bd7f8b0760 install_ffmpeg: Compile in more stuff for AI 2024-08-09 12:43:42 -07:00
Rick Staa a50164a87b docs: improve test instructions (#412)
This commit ensures that people are aware that they need to add the
compiled vrsion of ffmpeg to the PATH to be able to run the tests.
2024-07-26 22:06:52 +02:00
Rick Staa 409f6e0d87 Merge pull request #411 from livepeer/improve_docs
docs: update README with extra dev info
2024-07-25 19:15:33 +02:00
kevincatty 4b092b8fc6 chore: fix some typos in comment (#397)
Signed-off-by: kevincatty <zhanshanmao@outlook.com>
2024-07-25 09:27:29 -07:00
Chase Media 5d250f1833 Fixed typo in vidplayer logging (#390) 2024-07-25 09:26:40 -07:00
Josh Allmann 956ccf4d08 Fix typo in params field (#409) 2024-07-25 09:08:51 -07:00
Josh Allmann 144a983869 Remove unused transcoder2 (#410) 2024-07-25 09:08:29 -07:00
Rick Staa 24ce26985c docs: update README with extra dev info
This commit ensure that developers are aware of the extra build flags
they have to run when installing ffmpeg for the tests to be succesfull.
It also cleans up the README a bit.
2024-07-25 16:11:41 +02:00
Josh Allmann d9c78b62ef Update FFmpeg to 7.0.1 (#406)
* Port install_ffmpeg.sh from go-livepeer

* Update ffmpeg and nv-codec-headers versions.

* Use local install_ffmpeg.sh in github CI

* Update transcoder for ffmpeg 7.0.1

* Update tests to be compatible with ffmpeg7 binary

* Fix FPS passthrough

* 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)
2024-07-10 20:45:24 -07:00
Josh Allmann 3db1a12ba0 Update nvidia tests to pass with VFR changes.
The nvidia test suite was never run after #393 so this breakage
was not noticed.
2024-07-10 12:39:33 -07:00