Skip to content

linux runing error init PeerConnectionFactory cannot open /tmp/libwebrtc-java-linux-x86_xxxx.so: libXfixes.so.3 #228

@SuperRookieMam

Description

@SuperRookieMam
  1. 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:
  2. 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
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions