Wrong Color DirectMediaPlayer VLCj and Libgdx

772 views Asked by At

I use Libgdx and VLCj to play video, but the color is wrong (the left side on the image is ok). I use DirectMediaPlayer to catch frame data from the memory, create texture and draw on the screen.

enter image description here

My code:

import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.direct.BufferFormat;
import uk.co.caprica.vlcj.player.direct.BufferFormatCallback;
import uk.co.caprica.vlcj.player.direct.DirectMediaPlayer;
import uk.co.caprica.vlcj.player.direct.RenderCallbackAdapter;
import uk.co.caprica.vlcj.player.direct.format.RV32BufferFormat;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
import uk.co.caprica.vlcj.runtime.x.LibXUtil;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Gdx2DPixmap;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;

public class MyGdxGame implements ApplicationListener {
    private OrthographicCamera camera;
    private Texture texture;

    private BitmapFont font;
    private SpriteBatch batch;

    float w = 800;
    float h = 600;

    private BufferedImage image;

    private MediaPlayerFactory factory;
    private DirectMediaPlayer mediaPlayer;
    private Pixmap pixmap;

    @Override
    public void create() {
        w = Gdx.graphics.getWidth();
        h = Gdx.graphics.getHeight();

        camera = new OrthographicCamera();
        camera.setToOrtho(false, w, h);
        camera.update();

        font = new BitmapFont();
        batch = new SpriteBatch();

        LibXUtil.initialise();
        NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Users\\Dima\\Desktop\\vlc-2.1.0_64\\");

        Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);

        image = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage((int) w, (int) h);
        image.setAccelerationPriority(1.0f);

        String[] args = { "--no-video-title-show", "--verbose=3" };
        String media = "C:\\video512.mp4";

        factory = new MediaPlayerFactory(args);
        mediaPlayer = factory.newDirectMediaPlayer(new TestBufferFormatCallback(), new TestRenderCallback());
        mediaPlayer.playMedia(media);

        System.out.println(LibVlc.INSTANCE.libvlc_get_version());
    }

    @Override
    public void dispose() {
        Gdx.app.exit();
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        batch.begin();
        if (pixmap != null) {
            texture = new Texture(pixmap);
            batch.draw(texture, 0, 0, 800, 600);
        }

        font.draw(batch, "FPS: " + Gdx.graphics.getFramesPerSecond(), 10, 20);
        batch.end();
    }

    private final class TestRenderCallback extends RenderCallbackAdapter {

        public TestRenderCallback() {
            super(((DataBufferInt) image.getRaster().getDataBuffer()).getData());
        }

        @Override
        public void onDisplay(DirectMediaPlayer mediaPlayer, int[] data) {    

            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder());
            IntBuffer intBuffer = byteBuffer.asIntBuffer();
            intBuffer.put(data);

            try {

                long[] nativeData = new long[] { 0, 800, 600, Gdx2DPixmap.GDX2D_FORMAT_RGBA8888 };
                Gdx2DPixmap pixmapData = new Gdx2DPixmap(byteBuffer, nativeData);

                pixmap = new Pixmap(pixmapData);
            } catch (Exception e) {
                pixmap = null;
                throw new GdxRuntimeException("Couldn't load pixmap from image data", e);
            }

        }
    }

    private final class TestBufferFormatCallback implements BufferFormatCallback {

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

    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

}

If you know others ways to draw video in java, let me know.

Solved!

Method getBufferFormat in TestBufferFormatCallback class was not correct. Right variant:

@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
    sourceWidth = 800;
    sourceHeight = 600;

    System.out.println("Got VideoFormat: " + sourceWidth + "x" + sourceHeight);

    BufferFormat format = new BufferFormat("RGBA", sourceWidth, sourceHeight, new int[] { sourceWidth * 4 }, new int[] { sourceHeight });

    return format;
}
0

There are 0 answers