Hi Marvin,

Thanks for the review.

> There is no need to split this in two commands

Good point I'll update the example to use git send-email directly against
origin/master.

> samples.ffmpeg.org is not the same thing as the FATE suite

I'll correct the rsync URL to fate.ffmpeg.org/fate-suite/ and fix the
surrounding prose.

> This would not be a proper test as it always succeeds

You're right the exit code needs to reflect the actual result. I'll fix the
example to return 1 on failure.

Will send a v2 shortly.

Thanks,
Marcos

On Sat, 14 Mar 2026 at 19:43, Marvin Scholz via ffmpeg-devel <
[email protected]> wrote:

>
> On 14 Mar 2026, at 20:17, marcos ashton via ffmpeg-devel wrote:
>
> > Add contributing.html covering building FFmpeg, submitting
> > patches via Forgejo, the review process, and writing FATE
> > tests for libavutil, libavfilter, and libavcodec.
> >
> > Sidebar nav left unchanged to avoid breaking bookmarks.
> >
> > Signed-off-by: marcos ashton <[email protected]>
>
> Some remarks inline below (not a full detailed review):
>
> > ---
> >  Makefile               |   2 +-
> >  src/contributing       | 410 +++++++++++++++++++++++++++++++++++++++++
> >  src/contributing_js    |   0
> >  src/contributing_title |   1 +
> >  4 files changed, 412 insertions(+), 1 deletion(-)
> >  create mode 100644 src/contributing
> >  create mode 100644 src/contributing_js
> >  create mode 100644 src/contributing_title
> >
> > diff --git a/Makefile b/Makefile
> > index dd681e4..4f5c187 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -1,6 +1,6 @@
> >  # ffmpeg.org HTML generation from source files
> >
> > -SRCS = about bugreports consulting contact donations documentation
> download \
> > +SRCS = about bugreports consulting contact contributing donations
> documentation download \
> >         olddownload index legal shame security spi archive
> >
> >  HTML_TARGETS  = $(addsuffix .html,$(addprefix htdocs/,$(SRCS)))
> > diff --git a/src/contributing b/src/contributing
> > new file mode 100644
> > index 0000000..d68aab2
> > --- /dev/null
> > +++ b/src/contributing
> > @@ -0,0 +1,410 @@
> > +<p>
> > +  This page covers everything a first-time contributor needs to get
> > +  started: building FFmpeg, submitting patches, understanding code
> review,
> > +  and writing tests.
> > +</p>
> > +
> > +<p>
> > +  For the full developer reference, see
> > +  <a href="developer.html">Developer Documentation</a> and
> > +  <a href="git-howto.html">Using Git to Develop FFmpeg</a>.
> > +</p>
> > +
> > +<br>
> > +
> > +<h3 id="BuildSetup">
> > +  <span class="pull-right">
> > +    <i class="fa fa-wrench"></i> &nbsp;
> > +  </span>
> > +  Building FFmpeg</h3>
> > +
> > +<p>
> > +  Clone the repository and build:
> > +</p>
> > +
> > +<pre>
> > +git clone https://git.ffmpeg.org/ffmpeg.git
> > +cd ffmpeg
> > +./configure
> > +make -j$(nproc)</pre>
> > +
> > +<p>
> > +  This builds ffmpeg, ffplay, and ffprobe. Run
> > +  <code>./configure --help</code> to see all options.
> > +</p>
> > +
> > +<p>
> > +  For development, you probably want debug symbols and test coverage:
> > +</p>
> > +
> > +<pre>
> > +./configure --toolchain=gcov --assert-level=2
> > +make -j$(nproc)</pre>
> > +
> > +<p>
> > +  Verify your build:
> > +</p>
> > +
> > +<pre>
> > +./ffmpeg -version</pre>
> > +
> > +<br>
> > +
> > +<h3 id="SubmittingPatches">
> > +  <span class="pull-right">
> > +    <i class="fa fa-code-fork"></i> &nbsp;
> > +  </span>
> > +  Submitting Patches</h3>
> > +
> > +<p>
> > +  The preferred way to submit patches is through
> > +  <a href="https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls";>Forgejo</a>
> > +  at code.ffmpeg.org. You can also send patches to the
> > +  <a href="https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-devel/
> ">ffmpeg-devel</a>
> > +  mailing list using <code>git format-patch</code> or
> > +  <code>git send-email</code>.
> > +</p>
> > +
> > +<p>
> > +  GitHub pull requests are not part of the review process and will be
> ignored.
> > +</p>
> > +
> > +<p><strong>Via Forgejo (recommended)</strong></p>
> > +
> > +<ol>
> > +  <li>Create an account at
> > +    <a href="https://code.ffmpeg.org";>code.ffmpeg.org</a>.</li>
> > +  <li>Fork the FFmpeg repository.</li>
> > +  <li>Push your branch to your fork.</li>
> > +  <li>Open a pull request against the main FFmpeg repository.</li>
> > +</ol>
> > +
> > +<p><strong>Via mailing list</strong></p>
> > +
> > +<p>
> > +  Generate and send patches:
> > +</p>
> > +
> > +<pre>
> > +git format-patch origin/master
> > +git send-email *.patch --to [email protected]</pre>
> > +
>
> There is no need to split this in two commands, you can just do:
>
> git send-email --to [email protected] origin/master
>
> and avoid the glob and possibly sending outdated patches again.
>
> > +<p>
> > +  Subscribe to ffmpeg-devel first. Patches from non-subscribers are held
> > +  for moderation and may be delayed. See
> > +  <a href="git-howto.html">Using Git to Develop FFmpeg</a> for
> > +  setup instructions.
> > +</p>
> > +
> > +<p><strong>Commit message format</strong></p>
> > +
> > +<p>
> > +  The first line must follow this format:
> > +</p>
> > +
> > +<pre>
> > +area/component: short description of what changed</pre>
> > +
> > +<p>
> > +  Then a blank line, then the body explaining why the change is needed.
> > +  The diff shows what changed; the message should explain why.
> > +  End with a Signed-off-by line (<code>git commit -s</code>).
> > +</p>
> > +
> > +<p>
> > +  Full example:
> > +</p>
> > +
> > +<pre>
> > +avcodec/libx264: fix memory leak in parameter parsing
> > +
> > +The options dictionary was not freed on the error path when
> > +x264_param_parse() returned a failure code.
> > +
> > +Signed-off-by: Your Name &lt;[email protected]&gt;</pre>
> > +
> > +<p>
> > +  Keep the first line under 72 characters. Each patch should be a single
> > +  logical change. Do not mix cosmetic changes with functional changes.
> > +  Run <code>tools/patcheck</code> on your patch before sending.
> > +</p>
> > +
> > +<br>
> > +
> > +<h3 id="ReviewProcess">
> > +  <span class="pull-right">
> > +    <i class="fa fa-comments"></i> &nbsp;
> > +  </span>
> > +  The Review Process</h3>
> > +
> > +<p>
> > +  Every patch is reviewed by other developers, whether you submit via
> > +  Forgejo or the mailing list. Here is what to expect:
> > +</p>
> > +
> > +<ol>
> > +  <li>A reviewer reads your patch and leaves comments. This may take
> > +    a few days. If you have not heard back after a week, send a
> > +    polite reminder or ask on <code>#ffmpeg-devel</code> on
> > +    <a href="https://libera.chat/";>Libera Chat</a>.</li>
> > +  <li>Address every comment. If you disagree with a suggestion, explain
> > +    your reasoning. Ignoring review comments will stall your patch.</li>
> > +  <li>Submit a revised version. On Forgejo, push to your branch. On the
> > +    mailing list, send a new version with <code>[PATCH v2]</code> in
> > +    the subject.</li>
> > +  <li>Repeat until the reviewer is satisfied. Simple patches may land
> > +    after one round. Larger patches often go through several
> > +    revisions.</li>
> > +  <li>Once approved, a developer with commit access pushes it to
> > +    master.</li>
> > +</ol>
> > +
> > +<p>
> > +  Reviewing other people's patches is one of the best ways to get your
> > +  own patches reviewed faster. Everyone is welcome to review.
> > +</p>
> > +
> > +<br>
> > +
> > +<h3 id="BeforeYouSubmit">
> > +  <span class="pull-right">
> > +    <i class="fa fa-check-square-o"></i> &nbsp;
> > +  </span>
> > +  Before You Submit</h3>
> > +
> > +<p>
> > +  Run the FATE test suite to make sure nothing is broken:
> > +</p>
> > +
> > +<pre>
> > +make fate</pre>
> > +
> > +<p>
> > +  Many tests require sample media files that are not included in the
> > +  source tree. Download them from
> > +  <a href="https://samples.ffmpeg.org";>samples.ffmpeg.org</a> (rsync
> > +  is the fastest method):
> > +</p>
>
> samples.ffmpeg.org is not the same thing as the FATE suite, afaik.
>
> > +
> > +<pre>
> > +rsync -a --no-inc-recursive rsync://fate.ffmpeg.org/fate-suite/
> fate-suite/</pre>
> > +
> > +<p>
> > +  Then tell <code>./configure</code> where the samples live, either
> > +  at configure time:
> > +</p>
> > +
> > +<pre>
> > +./configure --samples=/path/to/fate-suite</pre>
> > +
> > +<p>
> > +  or as a make variable:
> > +</p>
> > +
> > +<pre>
> > +make fate SAMPLES=/path/to/fate-suite</pre>
> > +
> > +<p>
> > +  Without sample files, tests that depend on them are skipped rather
> > +  than failed, so your basic build will still pass. But if your patch
> > +  touches a codec, demuxer, or filter that has sample-based tests, run
> > +  with samples to make sure nothing regressed.
> > +</p>
> > +
> > +<p>
> > +  If your patch changes expected output, update the reference files.
> > +  If your patch adds a new module (decoder, encoder, filter, muxer,
> > +  demuxer, parser, or bitstream filter), add a FATE test for it.
> > +</p>
> > +
> > +<p>
> > +  Check your patch for common issues:
> > +</p>
> > +
> > +<pre>
> > +tools/patcheck your-patch.diff</pre>
> > +
> > +<p>
> > +  See the
> > +  <a href="developer.html#Patch-submission-checklist">Patch Submission
> Checklist</a>
> > +  for the full list.
> > +</p>
> > +
> > +<br>
> > +
> > +<h3 id="WritingFATETests">
> > +  <span class="pull-right">
> > +    <i class="fa fa-flask"></i> &nbsp;
> > +  </span>
> > +  Writing FATE Tests</h3>
> > +
> > +<p>
> > +  FATE (FFmpeg Automated Testing Environment) is the regression test
> > +  suite. Tests are defined in <code>tests/fate/*.mak</code> files.
> > +  Reference outputs live in <code>tests/ref/fate/</code>. There are
> > +  three common patterns.
> > +</p>
> > +
> > +<p><strong>C unit tests (libavutil)</strong></p>
> > +
> > +<p>
> > +  For testing utility functions, write a standalone C program that
> > +  exercises the API and prints results to stdout.
> > +</p>
> > +
> > +<p>
> > +  Create the test at <code>libavutil/tests/yourtest.c</code>:
> > +</p>
> > +
> > +<pre>
> > +#include "libavutil/yourheader.h"
> > +
> > +int main(void)
> > +{
> > +    /* call the functions you want to test */
> > +    printf("some_function: %s\n", result ? "OK" : "FAIL");
> > +    return 0;
> > +}</pre>
>
> This would not be a proper test as it always succeeds from the PoV of
> make, as the exit status is 0 regardless of the outcome.
>
> > +
> > +<p>
> > +  Add it to <code>libavutil/Makefile</code>:
> > +</p>
> > +
> > +<pre>
> > +TESTPROGS += yourtest</pre>
> > +
> > +<p>
> > +  Register it in <code>tests/fate/libavutil.mak</code>:
> > +</p>
> > +
> > +<pre>
> > +FATE_LIBAVUTIL += fate-yourtest
> > +fate-yourtest: libavutil/tests/yourtest$(EXESUF)
> > +fate-yourtest: CMD = run libavutil/tests/yourtest$(EXESUF)</pre>
> > +
> > +<p>
> > +  Generate the reference output:
> > +</p>
> > +
> > +<pre>
> > +make fate-yourtest GEN=1</pre>
> > +
> > +<p>
> > +  This creates <code>tests/ref/fate/yourtest</code>. If your test only
> > +  checks exit codes and produces no meaningful stdout, add
> > +  <code>CMP = null</code>.
> > +</p>
> > +
> > +<p><strong>Filter tests (libavfilter)</strong></p>
> > +
> > +<p>
> > +  Filter tests run a filter chain and compare per-frame CRC checksums
> > +  against a reference. They go in
> > +  <code>tests/fate/filter-audio.mak</code> or
> > +  <code>tests/fate/filter-video.mak</code>.
> > +</p>
> > +
> > +<p>
> > +  Example for an audio filter:
> > +</p>
> > +
> > +<pre>
> > +FATE_AFILTER-$(call FILTERDEMDECENCMUX, YOURFILTER, WAV, PCM_S16LE,
> PCM_S16LE, WAV) += fate-filter-yourfilter
> > +fate-filter-yourfilter: tests/data/asynth-44100-2.wav
> > +fate-filter-yourfilter: SRC =
> $(TARGET_PATH)/tests/data/asynth-44100-2.wav
> > +fate-filter-yourfilter: CMD = framecrc -i $(SRC) -af yourfilter</pre>
> > +
> > +<p>
> > +  The <code>FILTERDEMDECENCMUX</code> macro checks that all required
> > +  components are compiled in. The <code>framecrc</code> command computes
> > +  a CRC for each output frame. Generate the reference:
> > +</p>
> > +
> > +<pre>
> > +make fate-filter-yourfilter GEN=1</pre>
> > +
> > +<p>
> > +  This writes the reference to
> > +  <code>tests/ref/fate/filter-yourfilter</code>. To test multiple
> > +  format variants, add separate entries with suffixes like
> > +  <code>fate-filter-yourfilter-fltp</code>.
> > +</p>
> > +
> > +<p><strong>Codec roundtrip tests (libavcodec)</strong></p>
> > +
> > +<p>
> > +  These encode audio or video with a codec, decode it back, and compare
> > +  the result against a reference. They live in
> > +  <code>tests/fate/acodec.mak</code>,
> > +  <code>tests/fate/vcodec.mak</code>, or a codec-specific
> > +  <code>.mak</code> file.
> > +</p>
> > +
> > +<p>
> > +  The generic template in <code>tests/fate/acodec.mak</code> handles
> > +  most audio codecs. To use it, add a single line:
> > +</p>
> > +
> > +<pre>
> > +FATE_ACODEC_LOSSLESS-$(call ENCDEC, YOURCODEC, WAV) += yourcodec</pre>
> > +
> > +<p>
> > +  This encodes <code>tests/data/asynth-44100-2.wav</code>, decodes it
> > +  back to PCM, and compares against
> > +  <code>tests/ref/acodec/yourcodec</code>.
> > +</p>
> > +
> > +<p>
> > +  For codecs that need custom options or lossy comparison:
> > +</p>
> > +
> > +<pre>
> > +FATE_ACODEC-$(call ENCDEC, YOURCODEC, WAV) += fate-acodec-yourcodec
> > +fate-acodec-yourcodec: CMD = enc_dec_pcm yourformat wav s16le $(SRC)
> -c:a yourcodec -b:a 128k
> > +fate-acodec-yourcodec: REF = $(SRC)
> > +fate-acodec-yourcodec: CMP = stddev
> > +fate-acodec-yourcodec: CMP_TARGET = 500</pre>
> > +
> > +<p>
> > +  <code>CMP = stddev</code> allows lossy comparison. The
> > +  <code>CMP_TARGET</code> value is the maximum allowed standard
> > +  deviation between original and decoded samples.
> > +</p>
> > +
> > +<br>
> > +
> > +<h3 id="GettingHelp">
> > +  <span class="pull-right">
> > +    <i class="fa fa-life-saver"></i> &nbsp;
> > +  </span>
> > +  Getting Help</h3>
> > +
> > +<div class="well">
> > +  <div class="list-group">
> > +    <a class="list-group-item"
> href="irc://irc.libera.chat/ffmpeg-devel">
> > +      <strong>#ffmpeg-devel on Libera Chat</strong><br>
> > +      Real-time discussion about FFmpeg development. Good for quick
> > +      questions and checking on patch status.
> > +    </a>
> > +    <a class="list-group-item" href="
> https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-devel/";>
> > +      <strong>ffmpeg-devel mailing list</strong><br>
> > +      Patch submission, review, and development discussion.
> > +      Subscribe before posting.
> > +    </a>
> > +    <a class="list-group-item" href="https://code.ffmpeg.org";>
> > +      <strong>Forgejo (code.ffmpeg.org)</strong><br>
> > +      The preferred platform for submitting pull requests.
> > +    </a>
> > +    <a class="list-group-item" href="https://trac.ffmpeg.org/wiki";>
> > +      <strong>FFmpeg Wiki</strong><br>
> > +      Community-maintained documentation, guides, and how-tos.
> > +    </a>
> > +  </div> <!-- list-group -->
> > +</div> <!-- well -->
> > +
> > +<p>
> > +  See also:
> > +  <a href="developer.html">Developer Documentation</a>,
> > +  <a href="git-howto.html">Using Git to Develop FFmpeg</a>, and
> > +  <a href="fate.html">FATE</a>.
> > +</p>
> > diff --git a/src/contributing_js b/src/contributing_js
> > new file mode 100644
> > index 0000000..e69de29
> > diff --git a/src/contributing_title b/src/contributing_title
> > new file mode 100644
> > index 0000000..cde9230
> > --- /dev/null
> > +++ b/src/contributing_title
> > @@ -0,0 +1 @@
> > +Contributing to FFmpeg
> > \ No newline at end of file
> > --
> > 2.53.0
> >
> > _______________________________________________
> > ffmpeg-devel mailing list -- [email protected]
> > To unsubscribe send an email to [email protected]
> _______________________________________________
> ffmpeg-devel mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
>
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to