-
-
Notifications
You must be signed in to change notification settings - Fork 85
Open
Description
- When I run the program in the Windows and Idea environment, it works normally. However, when I package it as a JAR service, it will report an error. The error message indicates that some files are missing in the dependencies. The code and the error message are as follows:
- I can find the file "libwebrtc-java-linux-x86_xxxx.so" under the /tmp folder. However, when I tried to extract this file, I couldn't locate the "libXfixes.so.3" file during the extraction process.
Could you please advise me on how to run it in the Linux environment using the jar package? Thanks.
dependency
<dependency>
<groupId>dev.onvoid.webrtc</groupId>
<artifactId>webrtc-java</artifactId>
<version>0.14.0</version>
</dependency>
code:
package com.shine.flight.control.models.zm.web;
import com.shine.flight.control.componet.api.system.util.AsyncUtil;
import com.shine.flight.control.componet.framework.common.exception.MyException;
import com.shine.flight.control.componet.framework.common.spring.ApplicationContextProvider;
import com.shine.flight.control.models.backend.domain.entity.LiveStreamFrame;
import com.shine.flight.control.models.backend.domain.enums.ContentTypeEnums;
import com.shine.flight.control.models.backend.domain.enums.LiveStreamFrameType;
import com.shine.flight.control.models.backend.domain.enums.OBSBusinessType;
import com.shine.flight.control.models.backend.service.ILiveStreamFrameService;
import com.shine.flight.control.models.flight.componet.util.TimeUtils;
import com.shine.flight.control.models.flight.domain.entity.Device;
import com.shine.flight.control.models.obs.componet.util.ObjectStorageUtil;
import com.shine.flight.control.models.obs.domain.dto.BucketDTO;
import com.shine.flight.control.models.obs.domain.dto.ObjectStorageMetaInfoDTO;
import com.shine.flight.control.models.obs.domain.dto.SignUrlDTO;
import com.shine.flight.control.models.obs.domain.enums.StorageTypeEnums;
import dev.onvoid.webrtc.*;
import dev.onvoid.webrtc.media.MediaStream;
import dev.onvoid.webrtc.media.MediaStreamTrack;
import dev.onvoid.webrtc.media.video.I420Buffer;
import dev.onvoid.webrtc.media.video.VideoDeviceSource;
import dev.onvoid.webrtc.media.video.VideoFrame;
import dev.onvoid.webrtc.media.video.VideoTrack;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@Slf4j
public class WhepUtil {
private final Device device;
private final BucketDTO bucket;
private final String whepEndPointUrl;
private PeerConnectionFactory factory;
private RTCPeerConnection peerConnection;
private RTCSessionDescription localOffer;
private final AtomicBoolean frameProcessed = new AtomicBoolean(false);
private final CountDownLatch frameLatch = new CountDownLatch(1);
private final CountDownLatch offerCreatedLatch = new CountDownLatch(1);
private final CountDownLatch localDescriptionSetLatch = new CountDownLatch(1);
private final CountDownLatch remoteDescriptionSetLatch = new CountDownLatch(1);
public WhepUtil(String whepEndpointUrl, Device device, BucketDTO bucket) {
this.whepEndPointUrl = whepEndpointUrl;
this.bucket = bucket;
this.device = device;
}
public void runCaptureFrame() {
try {
run();
} catch (Exception e) {
log.error("Error running WHEP", e);
} finally {
cleanup();
}
}
private void run() throws Exception {
log.info("Starting WebRTC Peer Connection");
initializePeerConnectionFactory();
createPeerConnection();
createOffer();
// Wait for the offer to be created.
if (!offerCreatedLatch.await(5, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timeout waiting for offer creation.");
}
// Set the local description (the offer).
setLocalDescription(localOffer);
// Wait for the local description to be set.
if (!localDescriptionSetLatch.await(5, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timeout waiting for local description to be set.");
}
log.info("Local offer created and set.");
log.info("Sending local offer to the remote endpoint.");
String answerSdp = sendOfferEndpoint(localOffer.sdp);
// Set the remote description (the answer).
setRemoteDescription(new RTCSessionDescription(RTCSdpType.ANSWER, answerSdp));
// Wait for the remote description to be set.
if (!remoteDescriptionSetLatch.await(5, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timeout waiting for remote description to be set.");
}
log.info("Remote answer set. Peer connection established!");
log.info("Media should now be exchanged between peers.");
// Wait for a frame to be captured and saved.
if (!frameLatch.await(10, TimeUnit.SECONDS)) {
throw new IllegalStateException("等待帧超时");
}
log.info("WebRTC Peer Connection completed.");
}
private void initializePeerConnectionFactory() {
log.info("Initializing PeerConnectionFactory.");
factory = new PeerConnectionFactory();
}
private void createPeerConnection() {
log.info("Creating peer connection.");
// Create ICE servers configuration.
RTCConfiguration config = new RTCConfiguration();
// Add Google's public STUN server.
RTCIceServer iceServer = new RTCIceServer();
iceServer.urls.add("stun:stun.l.google.com:19302");
config.iceServers.add(iceServer);
// Create the peer connection with our observer.
peerConnection = factory.createPeerConnection(config, new PeerConnectionObserverImpl());
// Create a video track from a video device source (e.g., webcam).
// Since we are only receiving video in this example, the source will be a dummy video source.
VideoDeviceSource videoSource = new VideoDeviceSource();
VideoTrack videoTrack = factory.createVideoTrack("videoTrack", videoSource);
// Only interested in receiving video, so we set up a transceiver for that.
RTCRtpTransceiverInit transceiverInit = new RTCRtpTransceiverInit();
transceiverInit.direction = RTCRtpTransceiverDirection.RECV_ONLY;
// Add the transceiver to the peer connection with the video track.
RTCRtpTransceiver transceiver = peerConnection.addTransceiver(videoTrack, transceiverInit);
// Set up a sink to handle incoming video frames.
MediaStreamTrack track = transceiver.getReceiver().getTrack();
if (track instanceof VideoTrack vTrack) {
vTrack.addSink(this::onVideoFrame);
}
}
private void createOffer() {
log.info("Creating offer.");
// Create offer options (use default options).
RTCOfferOptions options = new RTCOfferOptions();
// Create the offer.
peerConnection.createOffer(options, new CreateSessionDescriptionObserver() {
@Override
public void onSuccess(RTCSessionDescription description) {
log.info("Offer created successfully.");
localOffer = description;
offerCreatedLatch.countDown();
}
@Override
public void onFailure(String error) {
log.error("Failed to create offer: " + error);
offerCreatedLatch.countDown();
}
});
}
private void setLocalDescription(RTCSessionDescription description) {
log.info("Setting local description.");
peerConnection.setLocalDescription(description, new SetSessionDescriptionObserver() {
@Override
public void onSuccess() {
log.info("Local description set successfully.");
localDescriptionSetLatch.countDown();
}
@Override
public void onFailure(String error) {
log.error("Failed to set local description: " + error);
localDescriptionSetLatch.countDown();
}
});
}
private String sendOfferEndpoint(String sdpOffer) throws Exception {
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(whepEndPointUrl))
.header("Content-Type", "application/sdp")
.POST(HttpRequest.BodyPublishers.ofString(sdpOffer))
.timeout(Duration.ofSeconds(30))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200 || response.statusCode() == 201) {
log.info("WHEP request successful");
return response.body();
} else {
throw new RuntimeException("WHEP request failed with status: " + response.statusCode());
}
}
private void setRemoteDescription(RTCSessionDescription description) {
log.info("Setting remote description.");
peerConnection.setRemoteDescription(description, new SetSessionDescriptionObserver() {
@Override
public void onSuccess() {
log.info("Remote description set successfully.");
remoteDescriptionSetLatch.countDown();
}
@Override
public void onFailure(String error) {
log.info("Failed to set remote description: " + error);
remoteDescriptionSetLatch.countDown();
}
});
}
private void cleanup() {
log.info("Cleaning up resources.");
if (peerConnection != null) {
peerConnection.close();
peerConnection = null;
}
if (factory != null) {
factory.dispose();
factory = null;
}
}
private BufferedImage convertToBufferedImage(VideoFrame frame) {
// Convert the frame to a BufferedImage
int width = frame.buffer.getWidth();
int height = frame.buffer.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
// Convert I420 to BGR
I420Buffer i420;
try {
i420 = frame.buffer.toI420();
byte[] i420Data = I420BufferUtils.toByteArray(i420);
I420ToBGR(width, height, i420Data, data);
} catch (Exception e) {
log.error("Failed to convert I420 to BGR: sn:{}", device.getSn(), e);
throw new MyException("I420转换BGR失败");
}
return image;
}
private void I420ToBGR(int width, int height, byte[] i420Data, byte[] bgrData) {
int ySize = width * height;
int uOffset = ySize;
int vOffset = ySize + ySize / 4;
int uvWidth = width / 2;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int yIndex = y * width + x;
int uIndex = uOffset + (y / 2) * uvWidth + (x / 2); // FIXED
int vIndex = vOffset + (y / 2) * uvWidth + (x / 2); // FIXED
int yValue = (i420Data[yIndex] & 0xFF);
int uValue = (i420Data[uIndex] & 0xFF);
int vValue = (i420Data[vIndex] & 0xFF);
int c = yValue - 16;
int d = uValue - 128;
int e = vValue - 128;
int r = (int) Math.round(1.164 * c + 1.596 * e); // +1.596
int g = (int) Math.round(1.164 * c - 0.813 * e - 0.391 * d);
int b = (int) Math.round(1.164 * c + 2.018 * d);
int bgrIndex = (y * width + x) * 3;
bgrData[bgrIndex] = (byte) (clamp(b));
bgrData[bgrIndex + 1] = (byte) (clamp(g));
bgrData[bgrIndex + 2] = (byte) (clamp(r));
}
}
}
private int clamp(int v) {
return v < 0 ? 0 : Math.min(v, 255);
}
private void onVideoFrame(VideoFrame frame) {
// 一次只取一帧
if (!frameProcessed.compareAndSet(false, true)) {
try {
frame.release();
} catch (Exception e) {
log.error("frame释放失败", e);
}
return;
}
try {
BufferedImage bufferImage = convertToBufferedImage(frame);
AsyncUtil.doAsync(() -> bufferedImageHandler(bufferImage));
frameLatch.countDown();
} catch (Exception e) {
log.error("Failed to save frame: ", e);
} finally {
frame.release();
}
}
private void bufferedImageHandler(BufferedImage bufferImage) {
try {
byte[] imageToJpegBytes = bufferedImageToJpegBytes(bufferImage, 1f);
ObjectStorageMetaInfoDTO uploadResult = upload(imageToJpegBytes, bucket);
LiveStreamFrame liveStreamFrame = new LiveStreamFrame();
liveStreamFrame.setSn(device.getSn());
liveStreamFrame.setUrl(uploadResult.getUploadUrl());
liveStreamFrame.setUploadId(uploadResult.getId());
liveStreamFrame.setProjectUuid(device.getProjectUuid());
liveStreamFrame.setType(LiveStreamFrameType.DOCK.getCode());
ILiveStreamFrameService liveStreamFrameService = ApplicationContextProvider.getBeanOfType(ILiveStreamFrameService.class);
if (liveStreamFrameService != null) {
liveStreamFrameService.save(liveStreamFrame);
}
} catch (Exception e) {
log.error("抽帧数据保存失败 sn:{} ", device.getSn(), e);
}
}
public static byte[] bufferedImageToJpegBytes(BufferedImage bufferedImage, float quality) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// 使用ImageIO写JPEG,并尝试设置压缩质量
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpeg");
if (!writers.hasNext()) {
ImageIO.write(bufferedImage, "jpg", stream);
return stream.toByteArray();
}
ImageWriter writer = writers.next();
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// quality 范围 0..1
param.setCompressionQuality(Math.max(0f, Math.min(1f, quality)));
}
try (MemoryCacheImageOutputStream ios = new MemoryCacheImageOutputStream(stream)) {
writer.setOutput(ios);
writer.write(bufferedImage);
ios.flush();
} finally {
writer.dispose();
}
return stream.toByteArray();
}
public ObjectStorageMetaInfoDTO upload(byte[] bytes, BucketDTO bucket) {
SignUrlDTO url = new SignUrlDTO();
url.setBusinessType(OBSBusinessType.LIVE_STREAM_FRAME.getCode());
url.setBucketName(bucket.getBucketName());
url.setContentType(ContentTypeEnums.IMAGE_CONTENT_TYPE.getContentType());
url.setObjectName(String.format("%s.jpg", buildName()));
url.setFileSize((long) bytes.length);
return ObjectStorageUtil.uploadBy(StorageTypeEnums.HUA_WEI_YUN, url, bytes);
}
private String buildName() {
String sn = device.getSn();
return sn + "_" + TimeUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss");
}
private static class PeerConnectionObserverImpl implements PeerConnectionObserver {
@Override
public void onIceCandidate(RTCIceCandidate candidate) {
log.info("ICE candidate: " + candidate.sdp);
// In a real application, we would send this candidate to the remote peer
}
@Override
public void onConnectionChange(RTCPeerConnectionState state) {
log.info("Connection state changed: " + state);
}
@Override
public void onIceConnectionChange(RTCIceConnectionState state) {
log.info("ICE connection state changed: " + state);
}
@Override
public void onIceGatheringChange(RTCIceGatheringState state) {
log.info("ICE gathering state changed: " + state);
}
@Override
public void onSignalingChange(RTCSignalingState state) {
log.info("Signaling state changed: " + state);
}
@Override
public void onDataChannel(RTCDataChannel dataChannel) {
log.info("Data channel created: " + dataChannel.getLabel());
}
@Override
public void onRenegotiationNeeded() {
log.info("Renegotiation needed.");
}
@Override
public void onAddTrack(RTCRtpReceiver receiver, MediaStream[] mediaStreams) {
log.info("Track added.");
}
}
}
error
jakarta.servlet.ServletException: Handler dispatch failed: java.lang.UnsatisfiedLinkError: /tmp/libwebrtc-java-linux-x86_649408504446987946324.so: libXfixes.so.3: 无法打开共享对象文件: 没有那个文件或目录
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1096)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:365)
at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at com.shine.flight.control.componet.framework.security.core.provider.filter.CustomOncePerRequestFilter.doFilterInternal(CustomOncePerRequestFilter.java:45)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:128)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:151)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:129)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82)
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at com.shine.flight.control.models.system.componet.filter.CorsFilter.doFilter(CorsFilter.java:34)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at com.shine.flight.control.componet.framework.filter.BasicFilter.doFilter(BasicFilter.java:41)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.UnsatisfiedLinkError: /tmp/libwebrtc-java-linux-x86_649408504446987946324.so: libXfixes.so.3: 无法打开共享对象文件: 没有那个文件或目录
at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2389)
at java.base/java.lang.Runtime.load0(Runtime.java:755)
at java.base/java.lang.System.load(System.java:1953)
at dev.onvoid.webrtc.internal.NativeLoader.loadLibrary(NativeLoader.java:73)
at dev.onvoid.webrtc.PeerConnectionFactory.<clinit>(PeerConnectionFactory.java:42)
at com.shine.flight.control.models.zm.web.WhepUtil.initializePeerConnectionFactory(WhepUtil.java:129)
at com.shine.flight.control.models.zm.web.WhepUtil.run(WhepUtil.java:86)
at com.shine.flight.control.models.zm.web.WhepUtil.runCaptureFrame(WhepUtil.java:74)
at com.shine.flight.control.models.backend.service.schedule.CaptureFrameSchedule.doCaptureFrame(CaptureFrameSchedule.java:91)
at com.shine.flight.control.models.backend.service.schedule.CaptureFrameSchedule.captureFrame(CaptureFrameSchedule.java:75)
at com.shine.flight.control.models.system.web.controller.TestController.dockCaptureFrame(TestController.java:154)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at com.shine.flight.control.componet.framework.aop.advice.SingleHandlerMethodInterceptor.invoke(SingleHandlerMethodInterceptor.java:22)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:702)
at com.shine.flight.control.models.system.web.controller.TestController$$SpringCGLIB$$0.dockCaptureFrame(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
... 105 common frames omitted
Metadata
Metadata
Assignees
Labels
No labels