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> > + </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> > + </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 <[email protected]></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> > + </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> > + </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> > + </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> > + </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]
