Search code examples
javafxmedia-playermp4h.264shinobi

MediaPlayer silently fails to play H264/MPEG4 video


I would like to use MediaView to play video streams and video files generated by the Shinobi media server but MediaView does not seem to be able to handle any stream or file generated by Shinobi.

I am using Java 18 and JavaFX 19 (I have tried older versions as well).

I have one sample file generated by Shinobi here.

It plays fine in VLC, which shows that the file has the following attributes:

Codec: H264 - MPEG-4 AVC (part 10) (avc1)
Video resolution: 1280x720
Decoded format: Planar 4:2:2 YUV full scale
Chroma location: left

I have added error handlers to the MediaPlayer, MediaView and Media objects but there are no errors when I attempt to play the file.

Does anybody have any ideas as to why the player wouldn't like the file above?

Has anybody had success playing files from Shinobi (it uses FFMPEG under the covers.)?

It does play other files like:

https://coderslegacy.com/wp-content/uploads/2020/07/Pygame_Platformer-1.mp4";

I expect the video to play without errors or for the player to tell me why it can not play the video.

Here is my code:

package com.example.videotester;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaErrorEvent;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;

import java.io.File;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Button button1 = new Button("Play");
        Button button2 = new Button("Pause");
        Button button3 = new Button("Stop");

        String path = "C:/Users/Rob/Desktop/rlrO5DVBJS-2022-10-26T20-52-34.mp4";
        File f = new File(path);
        path = f.toURI().toString();
//        path="http://192.168.1.239:8080/532046fecc8da376f3f32f5518bad33b/videos/NUW6mXm9CF/rlrO5DVBJS/2022-10-26T14-32-07.mp4";
//        path="http://192.168.1.239:8080/2921f1ca7204e640734709e29fc2033f/hls/NUW6mXm9CF/rlrO5DVBJS/s.m3u8";
//        path="http://192.168.1.239:8080/2921f1ca7204e640734709e29fc2033f/h265/NUW6mXm9CF/rlrO5DVBJS/s.hevc";
//        path="http://192.168.1.239:8080/2921f1ca7204e640734709e29fc2033f/mp4/NUW6mXm9CF/rlrO5DVBJS/s.mp4";
//        path="http://192.168.1.239:8080/5ee9ca532fd17f860e3cef43a288b951/mjpeg/NUW6mXm9CF/rlrO5DVBJS"; //mjpeg
//        path="http://192.168.1.239:8080/f7fb8d581d5aab4ebb8732de13b61337/videos/NUW6mXm9CF/rlrO5DVBJS/2022-10-26T15-57-19.mp4";
//        path="http://192.168.1.239:8080/5ee9ca532fd17f860e3cef43a288b951/videos/NUW6mXm9CF/rlrO5DVBJS/2022-10-27T19-49-31.mp4";
//        path="http://192.168.1.239:8080/c6c8a86382548433c505d9e7cf7c2085/videos/NUW6mXm9CF/rlrO5DVBJS/2022-10-26T04-05-00.mp4";
//        path="https://coderslegacy.com/wp-content/uploads/2020/07/Pygame_Platformer-1.mp4";
//        path="https://www.dropbox.com/s/h1ky0he5dvclhkt/rlrO5DVBJS-2022-10-30T20-53-29.mp4?dl=0";
        //Instantiating Media class
//        Media media = new Media(new File(path).toURI().toString());
        //URL url = new URL(path);
        final Media media;
        final MediaPlayer mediaPlayer;
        MediaView mediaView  = null;
        try {
            media = new Media(path);
            if (media.getError() == null) {
                media.setOnError(() -> System.out.println("media player error : " + media.getError()));
                try {
                    mediaPlayer = new MediaPlayer(media);
                    mediaPlayer.setAutoPlay(true);
                    button1.setOnAction(e -> mediaPlayer.play());
                    button2.setOnAction(e -> mediaPlayer.pause());
                    button3.setOnAction(e -> mediaPlayer.stop());

                    mediaPlayer.setOnReady(() -> System.out.println("Video player ready"));

                    if (mediaPlayer.getError() == null) {
                        mediaPlayer.setOnError(() -> System.out.println("media player error : " + mediaPlayer.getError()));
                        mediaView = new MediaView(mediaPlayer);
                        mediaView.setOnError(mee -> System.out.println("media view error : " + t));
                    } else
                        System.out.println("Error in media player: " + mediaPlayer.getError());
                } catch (Exception mediaPlayerException) {
                    System.out.println("media player exception " + mediaPlayerException);
                }
            } else
                System.out.println("Error media creating media " + media.getError());
        } catch (Exception mediaException) {
            // Handle exception in Media constructor.
            System.out.println("Handle exception " + mediaException);
            System.exit(1);
        }

        GridPane layout = new GridPane();
        layout.setHgap(10);
        layout.setVgap(10);

        layout.add(button1, 0, 0);
        layout.add(button2, 1, 0);
        layout.add(button3, 2, 0);
        layout.add(mediaView, 0, 1, 4, 1);

        Scene scene = new Scene(layout, 300, 200);

        stage.setTitle("Video Player Tester");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

Solution

  • Rob - your file in https://www.dropbox.com/s/h1ky0he5dvclhkt/rlrO5DVBJS-2022-10-30T20-53-29.mp4?dl=0 has a color subsampling of 4:2:2 (color information scaled to 50%) most consumer video is 4:2:0 (color information scaled to 25%).

    The file at https://coderslegacy.com/wp-content/uploads/2020/07/Pygame_Platformer-1.mp4 is 4:2:0.

    I am guessing that the Java media player is passing the video to the operating system and the OS's default decoder may not support the higher color resolution of 4:2:2.