How to decode H.264 video frame in Java environment

前端 未结 5 861
迷失自我
迷失自我 2020-12-23 22:21

Does anyone know how to decode H.264 video frame in Java environment?

My network camera products support the RTP/RTSP Streaming.

The service standard RTP/RTS

5条回答
  •  渐次进展
    2020-12-23 22:46

    I found a very simple and straight-forward solution based on JavaCV's FFmpegFrameGrabber class. This library allows you to play a streaming media by wrapping the ffmpeg in Java.

    How to use it?

    First, you may download and install the library, using Maven or Gradle.

    Here you have a StreamingClient class that calls a SimplePlayer class that has Thread to play the video.

    public class StreamingClient extends Application implements GrabberListener
    {
        public static void main(String[] args)
        {
            launch(args);
        }
    
        private Stage primaryStage;
        private ImageView imageView;
    
        private SimplePlayer simplePlayer;
    
        @Override
        public void start(Stage stage) throws Exception
        {
            String source = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov"; // the video is weird for 1 minute then becomes stable
    
            primaryStage = stage;
            imageView = new ImageView();
    
            StackPane root = new StackPane();
    
            root.getChildren().add(imageView);
            imageView.fitWidthProperty().bind(primaryStage.widthProperty());
            imageView.fitHeightProperty().bind(primaryStage.heightProperty());
    
            Scene scene = new Scene(root, 640, 480);
    
            primaryStage.setTitle("Streaming Player");
            primaryStage.setScene(scene);
            primaryStage.show();
    
            simplePlayer = new SimplePlayer(source, this);
        }
    
        @Override
        public void onMediaGrabbed(int width, int height)
        {
            primaryStage.setWidth(width);
            primaryStage.setHeight(height);
        }
    
        @Override
        public void onImageProcessed(Image image)
        {
            LogHelper.e(TAG, "image: " + image);
    
            Platform.runLater(() -> {
                imageView.setImage(image);
            });
        }
    
        @Override
        public void onPlaying() {}
    
        @Override
        public void onGainControl(FloatControl gainControl) {}
    
        @Override
        public void stop() throws Exception
        {
            simplePlayer.stop();
        }
    }
    

    SimplePlayer class uses FFmpegFrameGrabber to decode a frame that is converted into an image and displayed in your Stage

    public class SimplePlayer
    {
        private static volatile Thread playThread;
        private AnimationTimer timer;
    
        private SourceDataLine soundLine;
    
        private int counter;
    
        public SimplePlayer(String source, GrabberListener grabberListener)
        {
            if (grabberListener == null) return;
            if (source.isEmpty()) return;
    
            counter = 0;
    
            playThread = new Thread(() -> {
                try {
                    FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(source);
                    grabber.start();
    
                    grabberListener.onMediaGrabbed(grabber.getImageWidth(), grabber.getImageHeight());
    
                    if (grabber.getSampleRate() > 0 && grabber.getAudioChannels() > 0) {
                        AudioFormat audioFormat = new AudioFormat(grabber.getSampleRate(), 16, grabber.getAudioChannels(), true, true);
    
                        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
                        soundLine = (SourceDataLine) AudioSystem.getLine(info);
                        soundLine.open(audioFormat);
                        soundLine.start();
                    }
    
                    Java2DFrameConverter converter = new Java2DFrameConverter();
    
                    while (!Thread.interrupted()) {
                        Frame frame = grabber.grab();
                        if (frame == null) {
                            break;
                        }
                        if (frame.image != null) {
    
                            Image image = SwingFXUtils.toFXImage(converter.convert(frame), null);
                            Platform.runLater(() -> {
                                grabberListener.onImageProcessed(image);
                            });
                        } else if (frame.samples != null) {
                            ShortBuffer channelSamplesFloatBuffer = (ShortBuffer) frame.samples[0];
                            channelSamplesFloatBuffer.rewind();
    
                            ByteBuffer outBuffer = ByteBuffer.allocate(channelSamplesFloatBuffer.capacity() * 2);
    
                            for (int i = 0; i < channelSamplesFloatBuffer.capacity(); i++) {
                                short val = channelSamplesFloatBuffer.get(i);
                                outBuffer.putShort(val);
                            }
                        }
                    }
                    grabber.stop();
                    grabber.release();
                    Platform.exit();
                } catch (Exception exception) {
                    System.exit(1);
                }
            });
            playThread.start();
        }
    
        public void stop()
        {
            playThread.interrupt();
        }
    }
    

提交回复
热议问题