Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

# Preserve whitespace in imported patch payloads and vendored SDK sources.
demos/dmabuf-browser/chromium/*.patch whitespace=-trailing-space
deps/ffmpeg-patches/*.patch whitespace=-trailing-space
deps/ffmpeg/8/*.patch whitespace=-trailing-space
deps/Optical_Flow_SDK_5.0.7/** whitespace=-trailing-space
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
## Code & logic style
* No copy-paste between nodes or within a file; extract shared base classes, utilities, or helper functions/lambdas.
* C++/Python project: prefer C++ idioms (RAII, exceptions) over C patterns, but don't over-apply OOP.
* Reuse libav* and avcpp before writing a helper: `av::Rational`/`av_inv_q`/`av_rescale*` for rates and timestamps,
`av::Timestamp` comparisons, `av_pix_fmt_*`/`av_image_*` for pixel-format geometry, `av_color_*_from_name` for colour
tags, `av_frame_*`/`av_*_metadata_alloc*` for frames and side data. A local reimplementation needs a comment saying
what libav lacks (e.g. the mixer's `TickGrid` rounding rule).

## Framework changes
* Don't modify framework source (graph management, control protocol, main, sentinel) unless explicitly asked or the change is necessary, generally useful, and future-proof.
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ override CXXFLAGS += -DSYNCMETER=1
endif

nodes_list_file = graph_factory.generated.cpp
CPPSRC = avplumber.cpp util.cpp avutils.cpp graph_core.cpp graph_mgmt.cpp stats.cpp output_control.cpp instance_shared.cpp hwaccel_mgmt.cpp EventLoop.cpp TickSource.cpp rest_client.cpp mixer/mixer_orchestrator.cpp
CPPSRC = avplumber.cpp util.cpp avutils.cpp graph_core.cpp graph_mgmt.cpp stats.cpp output_control.cpp instance_shared.cpp hwaccel_mgmt.cpp EventLoop.cpp TickSource.cpp rest_client.cpp mixer/TransitionScheduler.cpp mixer/graph_ops.cpp mixer/orchestrator/core.cpp mixer/orchestrator/scene.cpp mixer/orchestrator/cut.cpp mixer/orchestrator/fade.cpp mixer/orchestrator/wipe.cpp mixer/orchestrator/overlay.cpp
DEPS_LIBS = deps/cpr/build/lib/libcpr.a deps/avcpp/build/src/libavcpp.a
# Python extension links via PYTHON_MODULE_EXTRA_LFLAGS (python3-config; -lpython3 is not a valid soname on many distros).
LIBS_FLAGS = -lpthread -lcurl -lssl -lcrypto -lboost_thread -lboost_system -lavcodec -lavfilter -lavutil -lavformat -lavdevice -lswscale -lswresample -ldl -lz
Expand Down Expand Up @@ -162,8 +162,10 @@ $(eval $(call ptx_kernel,$(SRCDIR)/nodes/neural_net/preprocess/mask_assemble.cu,
endif

ifeq ($(HAVE_CUDA)$(HAVE_NVCC),11)
NODES_SRC += $(SRCDIR)/nodes/hwaccel/v210_to_cuda.cpp
$(eval $(call ptx_kernel,$(SRCDIR)/nodes/hwaccel/v210_unpack.cu,avpl_v210_unpack_ptx,objs/src/nodes/hwaccel/v210_to_cuda.o))
override CXXFLAGS += -DHAVE_CUDA_RECT_SCALE=1
$(eval $(call ptx_kernel,$(SRCDIR)/nodes/hwaccel/cuda_rect_scale.cu,avpl_rect_scale_ptx,objs/src/nodes/hwaccel/cuda_rect_overlay.o))
$(eval $(call ptx_kernel,$(SRCDIR)/nodes/hwaccel/cuda_rect_scale.cu,avpl_rect_scale_ptx,objs/src/nodes/hwaccel/cuda_rect_draw.o))
NODES_SRC += $(SRCDIR)/nodes/scene_cut/luma_diff.cpp
NODES_SRC += $(SRCDIR)/nodes/scene_cut/hog_diff.cpp
$(eval $(call ptx_kernel,$(SRCDIR)/nodes/scene_cut/luma_diff.cu,avpl_luma_diff_ptx,objs/src/nodes/scene_cut/luma_diff.o))
Expand All @@ -174,6 +176,7 @@ CUDA_ROOT ?= /usr/local/cuda
ifeq ($(HAVE_CUDA),1)
NODES_SRC += $(IPC_CUDA_SOURCE_SRC)
NODES_SRC += $(SRCDIR)/nodes/hwaccel/cuda_rect_overlay.cpp
NODES_SRC += $(SRCDIR)/nodes/hwaccel/cuda_rect_draw.cpp
override CPPSRC += cuda.cpp
override CXXFLAGS += -DHAVE_CUDA=1 -Iobjs -I$(CUDA_ROOT)/include -I$(CUDA_ROOT)/targets/x86_64-linux/include
override LFLAGS += -L$(CUDA_ROOT)/targets/x86_64-linux/lib -Wl,-rpath,$(CUDA_ROOT)/targets/x86_64-linux/lib
Expand Down
16 changes: 0 additions & 16 deletions avpmixer/__init__.py

This file was deleted.

106 changes: 0 additions & 106 deletions avpmixer/janus.py

This file was deleted.

2 changes: 1 addition & 1 deletion demos/dmabuf-browser/compose.mixer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ services:
MIXER_WIPE_FILE: ${MIXER_WIPE_FILE:-} # alpha clip inside the container to warm the wipe up with
volumes:
- dma-browser-sockets:/tmp/dma-page
- ../../avpmixer:/opt/avplumber/avpmixer:ro,z
- ../../pyplumber/mixer:/opt/avplumber/pyplumber/mixer:ro,z
- ../mixer:/opt/avplumber/demos/mixer:ro,z
command:
- sh
Expand Down
2 changes: 1 addition & 1 deletion demos/dmabuf-browser/consumer/Dockerfile.cuda
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ FROM nvidia/cuda:${CUDA_IMAGE_VERSION}-devel-ubuntu${UBUNTU_VERSION} AS builder

ARG DEBIAN_FRONTEND=noninteractive
ARG FFMPEG_TAG=n8.1
ARG NV_CODEC_HEADERS_TAG=n12.1.14.0
ARG NV_CODEC_HEADERS_TAG=n13.0.19.0 # SDK 13: HEVC/AV1 HDR10 mastering-display and MaxCLL SEIs (driver >= 570)
ARG CUDA_NVCC_FLAGS="-gencode arch=compute_70,code=compute_70 -O2"

RUN apt-get update \
Expand Down
3 changes: 1 addition & 2 deletions demos/mixer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM nvidia/cuda:11.7.1-devel-ubuntu22.04
ARG DEBIAN_FRONTEND=noninteractive
ARG AVPLUMBER_REVISION=workspace
ARG FFMPEG_TAG=n8.1
ARG NV_CODEC_HEADERS_TAG=n12.1.14.0
ARG NV_CODEC_HEADERS_TAG=n13.0.19.0

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
Expand Down Expand Up @@ -86,7 +86,6 @@ COPY deps /build/deps
COPY Makefile generate_node_list /build/
COPY src /build/src
COPY pyplumber /build/pyplumber
COPY avpmixer /build/avpmixer

RUN git init --quiet /build \
&& git -C /build config user.name "mixer-demo builder" \
Expand Down
37 changes: 35 additions & 2 deletions demos/mixer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,36 @@ Sixteen generated clips with visible frame IDs (needs NumPy and FFmpeg):
python3 demos/mixer/tests/frame_codes.py media --sources 16 --width 1920 --height 1080 --fps 60 --seconds 30
```

Eight colorful SDR patterns (bars, mandelbrot, life, ...) as NVENC clips:

```sh
python3 demos/mixer/tests/sdr_patterns.py media/patterns --fps 60 --seconds 20
```

## An HDR show

`make_config.py` also writes HDR shows: an HLG (or PQ) 10-bit canvas, sources
tagged with their color, HEVC Main10 on the program mountpoint and a
tone-mapped H.264 rendition for SDR viewers on a second one. A 16-source
1080p60 example, mixing an NVDEC HDR movie, HLG patterns, an SDR clip, browser
pages and the patterns above:

```sh
python3 demos/mixer/make_config.py --canvas 1920x1080 --fps 60 --color hlg --working-format p210le \
--sdr-port 5004 --bitrate-kbps 8000 --preset p5 \
hdr_movie=/media/hdr-movie.mp4 hlg_clip=/media/hlg-clip.mp4:hlg \
hdr_pattern0=/fixtures/hlg0.v210@1920x1080:hlg hdr_pattern1=/fixtures/hlg1.v210@1920x1080:hlg \
bunny=/media/bunny.mp4:sdr \
web_a=https://example.org/a@1920x1080 web_b=https://example.org/b@1920x1080 web_c=https://example.org/c@1920x1080 \
$(for p in testsrc2 bars rgbtest mandelbrot gradients life sierpinski cellauto; do echo sdr_$p=/media/patterns/$p.mp4:sdr; done) \
> hdr16.json
```

Untagged clips (`hdr_movie` here) are typed by their decoded frames, so a PQ
movie lands on the HLG canvas through `tonemap_cuda`; the `grid_16_page_0`
scene shows all sixteen. Browser sources need the `dma-page` service and the
DMA-BUF container flags from [docs/guide.md](docs/guide.md#docker).

## Under the hood

Janus output limits forced keyframes to one per 150 ms by default (9 frames at
Expand All @@ -159,10 +189,13 @@ next eligible frame. Periodic keyframes share the same limit.

Two compositor slots draw every scene; a transition filter blends them and the
wipe is one more layer in the same kernel, so nothing round-trips through the
CPU. Browser frames are converted from RGB to the NV12 canvas inside the draw
pass. The program is composited once and each rendition re-times and rescales
CPU. Browser frames are converted from RGB to the NV12, P010 or P210 canvas inside the
draw pass. The program is composited once and each rendition re-times and rescales
it, so a second output costs an encode, not another composite.

Limits: 32 sources per show, no runtime source changes, 16 boxes in the built-in layouts;
see [docs/config.md](docs/config.md#known-limitations).

Output files, Janus settings, layouts and tests: [docs/guide.md](docs/guide.md).
Measured samples and conditions: [runtime-load-1080p.json](docs/runtime-load-1080p.json),
[latency.md](docs/latency.md).
46 changes: 46 additions & 0 deletions demos/mixer/config.example.hdr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"canvas": {"width": 1920, "height": 1080, "fps": 60, "working_format": "p210le", "color": "hlg"},
"sources": [
{"id": "gen0", "kind": "v210", "path": "/fixtures/hlg0_1920x1080.v210", "width": 1920, "height": 1080, "color": "hlg"},
{"id": "cam", "kind": "video", "path": "/media/camera_sdr.mp4", "width": 1920, "height": 1080},
{"id": "page", "kind": "browser", "color": "sdr", "url": "https://<host>/lower-third", "width": 1920, "height": 1080}
],
"scenes": [
{
"id": "gen_full",
"items": [
{
"source": "gen0",
"dst": {"x": 0, "y": 0, "w": 1920, "h": 1080},
"fit": "cover"
}
]
},
{
"id": "cam_with_graphics",
"items": [
{
"source": "cam",
"dst": {"x": 0, "y": 0, "w": 1920, "h": 1080},
"fit": "cover"
},
{
"source": "gen0",
"dst": {"x": 1180, "y": 60, "w": 680, "h": 382},
"fit": "cover"
},
{
"source": "page",
"dst": {"x": 0, "y": 0, "w": 1920, "h": 1080}
}
]
}
],
"initial_scene": "cam_with_graphics",
"control": {"direct": true, "transition": "fade", "fade_seconds": 0.5},
"renditions": [
{"id": "hdr", "target": "janus", "port": 5006, "codec": "hevc_nvenc", "bitrate_kbps": 6000},
{"id": "sdr", "target": "janus", "port": 5004, "codec": "h264_nvenc", "bitrate_kbps": 4500, "tonemap": "mobius", "tonemap_param": 0.9},
{"id": "archive", "target": "/recordings/program_pq.ts", "codec": "hevc_nvenc", "color": "pq", "tonemap_peak": 10, "max_fall": 400, "bitrate_kbps": 12000}
]
}
6 changes: 6 additions & 0 deletions demos/mixer/config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,47 @@
{
"id": "page0",
"kind": "browser",
"color": "sdr",
"url": "https://<host>/page0",
"width": 1920,
"height": 1080
},
{
"id": "page1",
"kind": "browser",
"color": "sdr",
"url": "https://<host>/page1",
"width": 1920,
"height": 1080
},
{
"id": "page2",
"kind": "browser",
"color": "sdr",
"url": "https://<host>/page2",
"width": 1920,
"height": 1080
},
{
"id": "page3",
"kind": "browser",
"color": "sdr",
"url": "https://<host>/page3",
"width": 1920,
"height": 1080
},
{
"id": "page4",
"kind": "browser",
"color": "sdr",
"url": "https://<host>/page4",
"width": 1920,
"height": 1080
},
{
"id": "page5",
"kind": "browser",
"color": "sdr",
"url": "https://<host>/page5",
"width": 1920,
"height": 1080
Expand Down
Loading
Loading