Using libjitsi to send a WebRTC video stream from a server to a browser

I’m trying to send video to a browser over a WebRTC connection using libjitsi. I know others have succeeded in doing this. Any help would be appreciated. I’m desperately trying to find documentation for how to actually use libjitsi. The javadocs are all I’ve found and they don’t explain how the system works.
I have my server consuming the SDP Offer, I’m generating an SDP Answer that appears to be reasonable, and the browser accepts it. I have ICE4J doing something that appears to be reasonable.

That required hacking as ICE4J does not use ‘mid’ attributes that are compatible with the streams of the SDP Offer… instead forcing the stream name ‘video’ / ‘audio’ as the ‘mid’ value. That seems wrong, but it’s the only way I could make it work.

Anyway the next part of actually sending the video data remains a mystery.
Once the ICE Agent has terminated I try to create a MediaStream using:

new MediaStreamImpl(connector, device, srtpControl);

The connector is a DefaultStreamConnector constructed using the rtp/rtcp sockets from the ICE Agent (which actually only has one Component, I suspect because of rtcp-mux?)
srtpControl is an instance of DtlsControlImpl which has the remote fingerprints initialized from the Offer SDP.

The device is a custom class that at the moment provides a org.jitsi.impl.neomedia.jmfext.media.protocol.ivffile.DataSource. My goal is that all I should need to change when I have this working is the DataSource, so I can plug in the output of other codecs that I already have implemented on the server.

I add the dynamic RTP payload type from the Offer/Answer to the stream, set the media format, then start() the stream.

I see a bunch of “WARNING: Dropping a DTLS packet. This DtlsPacketTransformer has not been started successfully or has been closed.” and eventually I see this exception:

Aug. 02, 2020 5:01:18 P.M. org.jitsi.utils.logging.LoggerImpl log
INFO: video codec/freq: VP8/90000 Hz
Aug. 02, 2020 5:01:18 P.M. org.jitsi.utils.logging.LoggerImpl log
INFO: video remote IP/port: null/-1
Exception in thread “FMJ Thread: net.sf.fmj.media.ProcessEngine@6fad1b54[ net.sf.fmj.media.ProcessEngine@6fad1b54 ] ( realizeThread)” java.lang.NoClassDefFoundError: org/jitsi/impl/neomedia/codec/FFmpeg
at org.jitsi.impl.neomedia.codec.video.HFlip.doOpen(HFlip.java:150)
at org.jitsi.impl.neomedia.codec.AbstractCodec2.open(AbstractCodec2.java:412)
at net.sf.fmj.media.BasicFilterModule.doRealize(BasicFilterModule.java:83)
at net.sf.fmj.media.PlaybackEngine.buildTrackFromGraph(PlaybackEngine.java:579)
at net.sf.fmj.media.ProcessEngine$ProcGraphBuilder.buildTrackFromGraph(ProcessEngine.java:262)
at net.sf.fmj.media.ProcessEngine$ProcGraphBuilder.buildCustomGraph(ProcessEngine.java:239)
at net.sf.fmj.media.ProcessEngine$ProcGraphBuilder.buildGraph(ProcessEngine.java:252)
at net.sf.fmj.media.ProcessEngine$ProcTControl.buildTrack(ProcessEngine.java:688)
at net.sf.fmj.media.PlaybackEngine.doRealize1(PlaybackEngine.java:1135)
at net.sf.fmj.media.ProcessEngine.doRealize(ProcessEngine.java:1197)
at net.sf.fmj.media.RealizeWorkThread.process(BasicController.java:1145)
at net.sf.fmj.media.StateTransitionWorkThread.run(BasicController.java:1224)
Caused by: java.lang.ClassNotFoundException: org.jitsi.impl.neomedia.codec.FFmpeg
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
… 12 more

and a few more of the Dropping a DTLS packet warnings.

I’m not sure where things are going wrong. I welcome any help or pointers to better documentation or examples.

Thanks,

SWP