VLCJ: прямой рендеринг в VLCJ с использованием EmbeddedMediaPlayer с использованием CallbackVideoSurface с высокой загрузкой процессора - PullRequest
0 голосов
/ 02 мая 2020

Я успешно рендерил видео с помощью EmbeddedMediaPlayer с CallbackVideoSurface с моими собственными BufferFormatCallback и RenderCallback.

Но проблема заключается в методе отображения RenderCallback внутри, он создает много потоков, поэтому он потребляет высокий процессор Я не могу найти, что не так с моим кодом, если кто-то может мне помочь, это было бы здорово.

Вот мой код

VideoPlayerTest. java

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.ByteBuffer;
import java.util.ArrayList;

import javax.swing.JFrame;

import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.media.MediaRef;
import uk.co.caprica.vlcj.medialist.MediaList;
import uk.co.caprica.vlcj.medialist.MediaListRef;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface;
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormatCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.format.RV32BufferFormat;
import uk.co.caprica.vlcj.player.list.MediaListPlayer;
import uk.co.caprica.vlcj.player.list.MediaListPlayerEventAdapter;
import uk.co.caprica.vlcj.player.list.PlaybackMode;

public class VideoPlayerTest {

    private static VideoPlayerTest videoPlayerTest;

    private final JFrame frame;

    private final EmbeddedMediaPlayerComponent mediaPlayerComponent;

    private final EmbeddedMediaPlayer embeddedMediaPlayer;

    public static void main(String[] args) {
        videoPlayerTest = new VideoPlayerTest();
    }

    public VideoPlayerTest() {
        frame = new JFrame("My First Media Player");
        frame.setBounds(100, 100, 600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        ArrayList<FrameListener> listeners = new ArrayList<FrameListener>();

        MyVideoPanel myVideoPanel = new MyVideoPanel();
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowOpened(WindowEvent e) {
                listeners.add(myVideoPanel);
                super.windowOpened(e);
            }

            @Override
            public void windowClosing(WindowEvent e) {
                frame.setVisible(false);
                listeners.remove(myVideoPanel);
                if(listeners.isEmpty())
                {
                    embeddedMediaPlayer.controls().stop();
                    embeddedMediaPlayer.release();
                }
                frame.dispose();
                System.exit(0);
            }
        });



        BufferFormatCallback bufferFormatCallback = new BufferFormatCallback() {

            @Override
            public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
                return new RV32BufferFormat(1920, 1080);
            }

            @Override
            public void allocatedBuffers(ByteBuffer[] buffers) {
            }
        };  

        CallbackVideoSurface callbackVideoSurface = new CallbackVideoSurface(bufferFormatCallback, new MyRenderCallback(listeners, 1920, 1080), false, VideoSurfaceAdapters.getVideoSurfaceAdapter());

        mediaPlayerComponent = new EmbeddedMediaPlayerComponent();

        MediaPlayerFactory mediaPlayerFactory = mediaPlayerComponent.mediaPlayerFactory();

        embeddedMediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
        embeddedMediaPlayer.audio().setVolume(0);

        callbackVideoSurface.attach(embeddedMediaPlayer);

        embeddedMediaPlayer.videoSurface().set(callbackVideoSurface);
        embeddedMediaPlayer.videoSurface().attachVideoSurface();    


        MediaListPlayer mediaListPlayer = mediaPlayerFactory.mediaPlayers().newMediaListPlayer();

        mediaListPlayer.events().addMediaListPlayerEventListener(new MediaListPlayerEventAdapter() {
            @Override
            public void nextItem(MediaListPlayer mediaListPlayer, MediaRef item) {
                System.out.println("nextItem()");
            }
        });

        mediaListPlayer.mediaPlayer().setMediaPlayer(embeddedMediaPlayer);

        MediaList mediaList = mediaPlayerFactory.media().newMediaList();
        mediaList.media().add("{Media Path 1}");
        mediaList.media().add("{Media Path 2}");
        mediaList.media().add("{Media Path 3}");

        MediaListRef mediaListRef = mediaList.newMediaListRef();
        try {
            mediaListPlayer.list().setMediaList(mediaListRef);
        }
        finally {
            mediaListRef.release();
        }

        mediaListPlayer.controls().setMode(PlaybackMode.LOOP);

        mediaListPlayer.controls().play();

        frame.setContentPane(myVideoPanel);

        frame.setVisible(true);
    }
}

MyVideoPanel. java

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class MyVideoPanel extends JPanel implements FrameListener {
    private BufferedImage image;
    public void newFrameRecieved(BufferedImage image) {
        this.image = image;
        repaint();
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), null);
        g.dispose();
    }
}

FrameListener. java

import java.awt.image.BufferedImage;

@FunctionalInterface
public interface FrameListener
{
    public void newFrameRecieved(BufferedImage image);
}

MyRenderCallback. java

Я думаю, проблема в этом классе display method

import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.util.List;

import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.RenderCallback;


public class MyRenderCallback implements RenderCallback
{
    private List<FrameListener> videoSurfaces;
    private int width;
    private int height;
    private BufferedImage image;
    private int[] rgbBuffer;

    public MyRenderCallback(List<FrameListener> listeners, int width, int height)
    {
        this.width = width;
        this.height = height;
        this.videoSurfaces = listeners;
        this.image = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_ARGB);
        rgbBuffer = new int[image.getWidth() * image.getHeight()];
    }

    @Override
    public void display(MediaPlayer mediaPlayer, ByteBuffer[] nativeBuffers, BufferFormat bufferFormat) {
        synchronized (this.rgbBuffer) {
            nativeBuffers[0].asIntBuffer().get(rgbBuffer, 0, bufferFormat.getHeight() * bufferFormat.getWidth());
            image.setRGB(0, 0, image.getWidth(), image.getHeight(), rgbBuffer, 0, image.getWidth());
        }

        for(FrameListener fl: videoSurfaces) {
            fl.newFrameRecieved(this.image);
        }
    }
}
...