Commit Graph

81 Commits

Author SHA1 Message Date
JohannesItten 4899c4e9a6 pip perf fix 2026-07-09 23:43:58 +03:00
JohannesItten e489a730b8 decklink in timing fix 2026-07-09 23:35:31 +03:00
JohannesItten a3d0a338c5 cache removed 2026-07-09 23:26:08 +03:00
JohannesItten f9e7fe79d4 removed sync groups 2026-07-09 23:21:59 +03:00
JohannesItten 1f133507bf test pattern amplitude as param 2026-07-09 21:30:28 +03:00
JohannesItten 4973d0f9fc gaindb node 2026-07-09 20:48:07 +03:00
itten 8f28b2f768 gaindb node 2026-07-09 20:39:41 +03:00
itten 30202e112e Merge pull request 'Pip node' (#6) from pip-node into main
Reviewed-on: #6
2026-07-09 19:46:05 +03:00
JohannesItten c561bf569e wait fixes 2026-07-09 19:27:22 +03:00
JohannesItten f6985e0b21 logs + signals desc 2026-07-09 19:18:02 +03:00
JohannesItten 944f330eb3 fixes errors 2026-07-09 19:07:59 +03:00
JohannesItten 79e0e0e81a fixes TAI index 2026-07-09 18:56:39 +03:00
JohannesItten 041588b990 pip based 2026-07-09 18:31:53 +03:00
JohannesItten 3820d0eeb7 combiner.md 2026-07-09 15:49:35 +03:00
JohannesItten d2095d14d3 Read info about source from source/flow_def 2026-07-09 12:43:10 +03:00
JohannesItten d3ef011319 tons of fixes 2026-07-07 23:41:05 +03:00
JohannesItten 6c6225d831 fix: don't double-send status to command requester
load_graph/stop_node/start_node each called notify() (push to all
clients) and then sent a direct response — the requesting client
got two identical messages, breaking test recv sequencing.

Use thread_local tl_requester to skip the requesting connection
in the push. notify() is called synchronously from the command,
so the thread_local is visible from the status_cb. Other clients
still receive the push; the requester gets only the direct response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 22:39:09 +03:00
JohannesItten 59b2ee437c test: WebSocket API test suite (19 cases)
Covers connection, protocol robustness, get_status, load_graph,
stop/start_node, crash detection, and multi-client push.
Runs against a live studio-manager; --skip-nodes skips tests
that need node binaries and MXL.

Run: ./tests/.venv/bin/python3 tests/test_ws_api.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 22:26:28 +03:00
JohannesItten 32fe6aa22a fix: DeckLink macOS build — CFStringRef and CoreFoundation
GetDisplayName returns CFStringRef on macOS (not const char*).
Add #ifdef __APPLE__ handling in DeckLinkSender.hpp and
DeckLinkReceiver.hpp, and link -framework CoreFoundation in
decklinkin/decklinkout CMakeLists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 19:58:46 +03:00
JohannesItten 8dfeeacecd fix ndi->decklinkout slowdown 2026-07-07 19:50:09 +03:00
JohannesItten 370cbd89a2 fixes + cmake fixes for macos 2026-07-07 19:33:55 +03:00
JohannesItten 31346c48a6 NDIReceiver probe fix 2026-07-07 19:21:13 +03:00
JohannesItten cbe933eca3 and another one 2026-07-07 19:11:09 +03:00
JohannesItten 32b608ed3c DeckLinkSender green screen fix 2026-07-07 19:09:48 +03:00
JohannesItten 0b6e9ce46a fist API trys 2026-07-07 18:56:15 +03:00
itten 592686b6d7 Merge pull request 'Feature/decklink out' (#5) from feature/decklink-out into main
Reviewed-on: #5
2026-07-07 17:27:34 +03:00
JohannesItten 2d154e90dc fixes + refactoring + plan 2026-07-07 17:26:47 +03:00
itten 2faf2f9076 decklink + audio 2026-07-07 16:46:03 +03:00
JohannesItten 8e5ea3210a decklink out plan md 2026-07-06 02:25:14 +03:00
itten 0bdf486859 decklink-ndi.json defaults change 2026-07-06 02:13:56 +03:00
itten be601e358e Merge pull request 'Decklink in' (#4) from decklink-in into main
Reviewed-on: #4
2026-07-06 02:08:29 +03:00
JohannesItten 94da6f3283 audio support 2026-07-06 01:51:47 +03:00
JohannesItten 7847a8b70d fix: use IDeckLinkVideoBuffer::GetBytes for frame access
On Linux, GetBytes lives on IDeckLinkVideoBuffer (via QueryInterface),
not directly on IDeckLinkVideoInputFrame. Also restores StartAccess/
EndAccess around the copy for correct buffer lifecycle management.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 01:42:32 +03:00
JohannesItten e335461aac refactor: DeckLinkReceiver readability and error handling
DeckLinkReceiver:
- Group private members with section comments (SDK objects / sync / frame state)
- Change wait_for_format timeout param from uint64_t to int (matches
  std::chrono::milliseconds and all call sites)

decklinkin main.cpp:
- Wrap start_capture in try/catch — logs error and returns cleanly on
  device init failure (consistent with NDIInNode pattern)
- Remove redundant zero-init on frame_buf (vector<uint8_t> zero-inits anyway)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 01:38:13 +03:00
JohannesItten 640271384e refactor: DeckLinkReceiver cleanup and encapsulation
DeckLinkReceiver:
- Make InputCallback a private nested class — no longer exposed publicly
- DeckLinkReceiver owns all shared state (mutex, CVs, frame buffer)
- Replace get_input_callback() with clean wait_for_frame() API
- Fix device list leak: enumerate_devices stores raw IDeckLink* in
  raw_devices; destructor releases all of them + selected_device's AddRef
- Remove dead members: device_config, device_status, deckLink_notification
- Remove dead SourceInfo::stride field; rename SourceInfo → VideoInfo
- Remove dead video_source_info public member
- Remove printf; use no logging in receiver (caller logs)
- Remove commented-out notification code
- Fix dead return false after throw in enumerate_devices
- Fix dead null check after new InputCallback
- Replace IDeckLinkVideoBuffer QueryInterface with simpler GetBytes()
- Replace plain bool frame_ready/format_detected with consistent usage
  under mutex (no longer mixing atomic + CV pattern)
- Call StopStreams/DisableVideoInput in destructor
- Consistent snake_case naming throughout

decklinkin main.cpp:
- Rename NodeDeckLinkIn → DeckLinkInNode
- Get device_index from config().value("device_index", 0u)
- Remove unused includes: <time.h>, <algorithm>, <cstdio>, <DeckLinkAPI.h>
- Use clean receiver.wait_for_frame() instead of reaching into callback
- Use mxlGetCurrentIndex resync after sleep (consistent with other nodes)
- Fix return node.execute() (was node.execute(); return 0)
- Fix main() spacing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 01:34:01 +03:00
itten c60c5645ed working video setup 2026-07-06 01:27:19 +03:00
itten f37c576bdc Merge pull request 'Feature/video in' (#3) from feature/video-in into main
Reviewed-on: #3
2026-07-05 12:57:38 +03:00
JohannesItten a16cc7c3b7 docs: document .ts-only audio pacing limitation in videoin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:54:23 +03:00
JohannesItten 1496cc2e1e refactor: rename video port flow_id → video_flow_id everywhere
All nodes now use video_flow_id/audio_flow_id consistently:
- nodes/testpattern: flow_id → video_flow_id
- nodes/fakesink:    flow_id → video_flow_id
- graph.json:        from_port/to_port flow_id → video_flow_id
- studio-manager:    hardcoded build_graph edges + FlowGraph.hpp comment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:52:48 +03:00
JohannesItten 7047690647 fix: resync video_index to MXL clock to prevent falling behind
After each video frame sleep, use mxlGetCurrentIndex instead of a
simple +1 increment — if audio processing ate into the next frame's
time we now skip the stale index rather than writing a late grain.
Same pattern ndiin already uses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:49:23 +03:00
JohannesItten fe6b7b10ed fix: VideoReader crash on video-only file at EOF and dead bool return
- Guard swr_close/swr_init at EOF inside if (has_audio) — calling
  swr_init(nullptr) on a video-only file crashed at first loop
- Change open_file from bool to void — it never returned false, only
  threw, so the if (!open_file()) check in the constructor was dead code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:46:00 +03:00
JohannesItten 0298cf9b48 refactor: VideoReader and videoin post-audio review cleanup
VideoReader:
- Remove unused #include <iostream>
- Remove dead AudioInfo::samples and ::channel_stride fields
- Rename have_video → has_video (consistent with has_audio)
- Rename get_next_frame → read_next (returns audio too, not just frames)
- Fix outdated comment on read_next
- Remove trailing blank line in allocate_audio_conversion_buffers

videoin:
- Remove redundant FFmpeg includes (VideoReader.hpp provides them)
- Fix bug: mxlFlowWriterGetMaxWriteLengthSamples called with invalid
  audio_writer when mxlCreateFlowWriter fails — moved inside else branch
- Rename call site: get_next_frame → read_next
- Rename have_video → has_video at call sites
- Use = nullptr for audio_writer (consistent with video_writer)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:44:35 +03:00
itten 166efc3c59 Some fixes. For a now we fully support only .ts, due to huge problem with h264/hevc audio bursts 2026-07-05 12:39:06 +03:00
itten b2534efb0f audio works, holy shit 2026-07-04 03:24:20 +03:00
JohannesItten 96475acf62 refactor: VideoReader and videoin cleanup
VideoReader:
- Guard get_source_info/allocate_conversion_buffers behind have_video
  check — prevents crash on audio-only files
- Remove unused audiobuf parameter from get_next_frame
- Remove dead return statements after throw
- Remove unused SourceInfo::stride field and AudioInfo struct
- Pass const std::string& instead of by value in constructor/open_file
- Remove redundant struct keyword on SourceInfo source_info{}
- Fix video_stream_index never guarded against -1 in open_file
- Check av_image_alloc and avcodec_parameters_to_context return values
- Remove extra av_packet_unref after seek (was harmless but confusing)
- Use SWS_BILINEAR for sws_getContext flags instead of 0
- Replace NULL with nullptr in sws_getContext
- Remove unused #include <libavutil/pixdesc.h>

videoin main.cpp:
- Early return if have_video is false after open
- Inline make_video_flow_def call (remove intermediate variable)
- Add grain count log line matching other nodes
- Change continue to break when get_next_frame returns false
- Make video_rate const
- Remove double blank line before main()
- Remove trailing spaces

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 19:13:19 +03:00
JohannesItten bb7d1bb5a3 fix: VideoReader bugs — stride, memory, audio detection, UB
Pass MXL grain stride (from sliceSizes[0]) into get_next_frame so
YUV422P10toV210 writes with the correct line width instead of a
self-computed value that may not match the MXL buffer.

Fix audio stream detection: condition was inverted (!= -1 → == -1),
so the first audio stream was never picked up.

Add return false at end of get_next_frame to fix UB when g_running
goes false and the loop exits without returning.

Replace av_frame_unref/av_packet_unref with av_frame_free/av_packet_free
in destructor — unref only releases data, not the struct itself.

Add av_freep(&p10_data[0]) in destructor to free av_image_alloc memory.

Remove unused p10_buffer and v210_buffer allocations.

Read filename from config("file") instead of hardcoded path.
Add early return if mxlCreateFlowWriter fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 19:11:18 +03:00
itten 0b5b113d4e fixed ndiout flow_id -> video_flow_id 2026-07-03 18:51:10 +03:00
itten 32a8fa9837 refactored videoin to NodeBase 2026-07-03 18:48:11 +03:00
itten 2c43f356d1 it's alive 2026-07-03 14:01:13 +03:00
JohannesItten a422cd832a feat: graph-level fanout — reuse flow UUID for same from_node+from_port
Edges that share the same source node and port now get the same MXL flow
UUID. One writer, multiple independent readers — each tracks its own
position in the ring buffer. Enables 1-to-N routing in graph.json without
any splitter node.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:43:41 +03:00