Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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