Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ runs:
key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-${{ hashFiles('webrtc-jni/pom.xml') }}
restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-

- name: Derive the FFmpeg version from the pom
run: echo "FFMPEG_VERSION=$(sed -n 's|.*<ffmpeg.version>\([^<]*\)</ffmpeg.version>.*|\1|p' webrtc-java-media/pom.xml)" >> "$GITHUB_ENV"
shell: bash

- name: Set up FFmpeg cache
uses: actions/cache@v4
with:
path: ~/ffmpeg
key: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-${{ hashFiles('webrtc-java-media/pom.xml') }}
restore-keys: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-

- name: Set up Maven cache
uses: actions/cache@v4
with:
Expand Down
3 changes: 2 additions & 1 deletion .github/actions/prepare-linux/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ runs:
- name: Install required packages
run: |
sudo apt update
sudo apt install -y binutils cmake git locales lsb-release ninja-build pipewire pipewire-pulse pkg-config python3 python3-setuptools rsync unzip wget xz-utils
# nasm is what FFmpeg assembles its x86 code with.
sudo apt install -y binutils cmake git locales lsb-release nasm ninja-build pipewire pipewire-pulse pkg-config python3 python3-setuptools rsync unzip wget xz-utils

# Chromium Clang to be used with the clang toolchain file
#curl -s https://raw.githubusercontent.com/chromium/chromium/main/tools/clang/scripts/update.py | python3 - --output-dir=/opt/clang
Expand Down
3 changes: 3 additions & 0 deletions .github/actions/prepare-macos/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ runs:
run: |
# Required on macos-14
brew install python-setuptools
# nasm is what FFmpeg assembles its x86 code with, which the Intel
# build needs even though the runner itself is Apple Silicon.
brew install nasm
shell: bash

- name: Select Xcode version
Expand Down
13 changes: 13 additions & 0 deletions .github/actions/prepare-windows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,16 @@ runs:
run: |
choco install ninja
shell: powershell

- name: Install MSYS2 and the FFmpeg build tools
run: |
# FFmpeg's configure and makefiles are shell scripts, so building it
# needs a POSIX shell even with MSVC, and that shell has to carry make
# and nasm. Git for Windows' bash carries neither.
if (-not (Test-Path "C:\msys64\usr\bin\bash.exe")) {
choco install msys2 --no-progress -y
}
C:\msys64\usr\bin\bash.exe -lc "pacman -Sy --noconfirm && pacman -S --needed --noconfirm make nasm diffutils pkgconf"
# Where the media module's CMake looks for it.
"MSYS2_ROOT=C:\msys64" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
shell: powershell
11 changes: 11 additions & 0 deletions .github/actions/release/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ runs:
key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-${{ hashFiles('webrtc-jni/pom.xml') }}
restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-

- name: Derive the FFmpeg version from the pom
run: echo "FFMPEG_VERSION=$(sed -n 's|.*<ffmpeg.version>\([^<]*\)</ffmpeg.version>.*|\1|p' webrtc-java-media/pom.xml)" >> "$GITHUB_ENV"
shell: bash

- name: Set up FFmpeg cache
uses: actions/cache@v4
with:
path: ~/ffmpeg
key: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-${{ hashFiles('webrtc-java-media/pom.xml') }}
restore-keys: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-

- name: Set up Maven cache
uses: actions/cache@v4
with:
Expand Down
41 changes: 39 additions & 2 deletions .github/actions/test-natives/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,50 @@ runs:
- name: Install the natives into the local repository
run: |
VERSION=$(sed -n '0,/<version>/s|.*<version>\([^<]*\)</version>.*|\1|p' pom.xml)
JAR=$(ls natives/webrtc-java-*.jar | head -n 1)
JAR=$(find natives -path '*webrtc-jni*' -name 'webrtc-java-*.jar' | head -n 1)
echo "Installing $JAR as webrtc-java:$VERSION:${{ inputs.classifier }}"
mvn -B -q install:install-file -Dfile="$JAR" -DgroupId=dev.onvoid.webrtc \
-DartifactId=webrtc-java -Dversion="$VERSION" -Dpackaging=jar \
-Dclassifier=${{ inputs.classifier }}
shell: bash

# Both native libraries go into the directory the media module's tests
# already read from, which is where its own build collects them. That is
# what puts them on the class path, and it is also what makes the reactor
# below work: webrtc-java's natives are a classifier artifact of a module
# that is in that reactor, and Maven answers a dependency on such a thing
# with the module's output directory, which holds no native library at
# all. Coming from a directory instead, they are simply found.
- name: Unpack the natives where the tests look for them
run: |
MEDIA_JAR=$(find natives -name 'webrtc-java-media-*-${{ inputs.classifier }}.jar' | head -n 1)
WEBRTC_JAR=$(find natives -path '*webrtc-jni*' -name 'webrtc-java-*.jar' | head -n 1)

if [ -z "$MEDIA_JAR" ]; then
echo "No webrtc-java-media natives for ${{ inputs.classifier }} in the artifact" >&2
exit 1
fi

MEDIA_JAR="$PWD/$MEDIA_JAR"
WEBRTC_JAR="$PWD/$WEBRTC_JAR"

mkdir -p webrtc-java-media/target/natives
cd webrtc-java-media/target/natives
# jar rather than unzip: the JDK is set up above, and unzip is not on
# every runner image.
"$JAVA_HOME/bin/jar" xf "$MEDIA_JAR"
"$JAVA_HOME/bin/jar" xf "$WEBRTC_JAR"
rm -rf META-INF
ls -l
shell: bash

# One reactor for both, so that webrtc-java-media resolves webrtc-java
# from it. Testing rather than installing: webrtc attaches the host
# natives from webrtc-jni/target during its package phase, and on a runner
# that only downloaded them there is no such directory.
#
# The native build is off: these natives were cross compiled by another
# job, and this runner is here to run them, not to build them again.
- name: Test
run: mvn -B -pl webrtc test -P${{ inputs.profile }}
run: mvn -B -pl webrtc,webrtc-java-media test -DskipNativeBuild -P${{ inputs.profile }}
shell: bash
17 changes: 15 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
# The media module builds FFmpeg from its third-party submodule.
submodules: true

- id: prepare
name: Prepare build
Expand All @@ -53,7 +56,9 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: natives-${{ matrix.platform.name }}
path: webrtc-jni/target/webrtc-java-*.jar
path: |
webrtc-jni/target/webrtc-java-*.jar
webrtc-java-media/target/webrtc-java-media-*.jar
if-no-files-found: error

build-linux:
Expand All @@ -72,6 +77,9 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
# The media module builds FFmpeg from its third-party submodule.
submodules: true

- id: prepare
name: Prepare build
Expand All @@ -91,7 +99,9 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: natives-${{ matrix.platform.name }}
path: webrtc-jni/target/webrtc-java-*.jar
path: |
webrtc-jni/target/webrtc-java-*.jar
webrtc-java-media/target/webrtc-java-media-*.jar
if-no-files-found: error

build-macos:
Expand All @@ -108,6 +118,9 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
# The media module builds FFmpeg from its third-party submodule.
submodules: true

- id: prepare-build
name: Prepare build
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ jobs:
uses: actions/checkout@v6
with:
fetch-tags: true
# The media module builds FFmpeg from its third-party submodule.
submodules: true

- name: Get tag from current branch
id: tag-selector
Expand Down Expand Up @@ -189,6 +191,8 @@ jobs:
uses: actions/checkout@v6
with:
fetch-tags: true
# The media module builds FFmpeg from its third-party submodule.
submodules: true

- name: Get tag from current branch
id: tag-selector
Expand Down Expand Up @@ -227,6 +231,8 @@ jobs:
uses: actions/checkout@v6
with:
fetch-tags: true
# The media module builds FFmpeg from its third-party submodule.
submodules: true

- name: Get tag from current branch
id: tag-selector
Expand Down
6 changes: 3 additions & 3 deletions docs/guide/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ The [`MediaFileExample`](https://github.com/devopvoid/webrtc-java/blob/master/we

This example is useful for applications that stream pre-recorded media, or that need a dependable stand-in for a camera in testing.

::: warning
This example needs the `webrtc-java-media` module, which is opt-in while it is being brought up on every platform, so it is built and run with the `with-media-extension` profile:
::: info
This example needs the `webrtc-java-media` module, which builds FFmpeg from the `third-party/ffmpeg` submodule. Make sure the submodule is checked out before building, as the [Media Files](/guide/media/media-files) guide describes.

```bash
mvn -Pwith-media-extension exec:java -D"exec.mainClass=dev.onvoid.webrtc.examples.MediaFileExample" -D"exec.args=movie.mp4"
mvn exec:java -D"exec.mainClass=dev.onvoid.webrtc.examples.MediaFileExample" -D"exec.args=movie.mp4"
```
:::

Expand Down
24 changes: 15 additions & 9 deletions docs/guide/media/media-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ Sending a file is a common need: a test pattern instead of a webcam, a pre-recor

Decoding happens entirely in native code. Frames never travel through Java: the module hands decoded pictures straight to the native side of a `CustomVideoSource`, and 10 ms chunks to a `CustomAudioSource`. They are paced in real time and carry the presentation times of the file, so what a receiver gets keeps the timing of the media rather than the timing of a Java thread.

::: warning Opt-in while it is being brought up
The media module is not part of the default build yet, and its native library has so far been built for `windows-x86_64` only. Build it with the `with-media-extension` profile, as described below.
:::

## Adding the Module

The module builds FFmpeg from a submodule pinned to a release tag, so the submodule has to be present:
The module is part of the normal build, and it builds FFmpeg from a submodule pinned to a release tag, so the submodule has to be present:

```shell
git submodule update --init --depth 1 webrtc-java-media/third-party/ffmpeg
mvn install -Pwith-media-extension
mvn install
```

Building FFmpeg needs `make` and `nasm`. On Windows they come from MSYS2:
Expand All @@ -34,17 +30,27 @@ C:\msys64\usr\bin\bash -lc "pacman -S --needed make nasm diffutils pkgconf"

Maven still runs from an ordinary shell; the build enters MSYS2 and the Visual Studio environment on its own. The first build compiles FFmpeg, which takes a while; later builds reuse the install directory.

Once installed, depend on it alongside `webrtc-java`:
Once installed, depend on it alongside `webrtc-java`. It takes two entries: one for the Java API, and one for the natives of the platform you are running on.

```xml
<dependency>
<groupId>dev.onvoid.webrtc</groupId>
<artifactId>webrtc-java-media</artifactId>
<version>0.19.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>dev.onvoid.webrtc</groupId>
<artifactId>webrtc-java-media</artifactId>
<version>0.19.0-SNAPSHOT</version>
<classifier>windows-x86_64</classifier>
</dependency>
```

The classifier jar carries the module's native library together with the FFmpeg shared libraries it uses. Applications that do not use this module never download FFmpeg.
The classifier jar carries the module's native library together with the FFmpeg shared libraries it uses, so applications that do not use this module never download FFmpeg. Replace the classifier with the platform you are building for: `windows-x86_64`, `windows-aarch64`, `linux-x86_64`, `linux-aarch64`, `linux-aarch32`, `macos-x86_64` or `macos-aarch64`.

::: info
Unlike `webrtc-java`, which brings its natives along by itself, this module cannot: the natives are built by the module rather than by a separate one, so a dependency on them would have nothing to resolve against on a first build. Asking for them explicitly is the price of that.
:::

## Sending a File

Expand Down Expand Up @@ -228,5 +234,5 @@ The module uses FFmpeg under the LGPL version 2.1 or later. It is configured wit
See `MediaFileExample` in the `webrtc-examples` module, which opens a file, reports what it contains, creates tracks, adds them to a peer connection and follows playback to the end.

```shell
mvn -Pwith-media-extension -pl webrtc-examples compile
mvn -pl webrtc-examples compile
```
14 changes: 1 addition & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<modules>
<module>webrtc-jni</module>
<module>webrtc</module>
<module>webrtc-java-media</module>
<module>webrtc-examples</module>
</modules>

Expand Down Expand Up @@ -354,19 +355,6 @@
<platform.module>webrtc.macos.aarch64</platform.module>
</properties>
</profile>
<!--
The FFmpeg based media extension. Opt-in while it is being brought
up on every platform: it builds FFmpeg from the
webrtc-java-media/third-party/ffmpeg submodule, which has build
requirements of its own (make, nasm, pkg-config) that the rest of
the project does not have.
-->
<profile>
<id>with-media-extension</id>
<modules>
<module>webrtc-java-media</module>
</modules>
</profile>
</profiles>

<dependencies>
Expand Down
Loading
Loading