简体   繁体   English

可以使用javacv / ffmpeg将h264流式传输到javafx

[英]Stream h264 to javafx possibly using javacv/ffmpeg

I'm really stuck on getting a video stream to play on a java fx project. 我真的很想让视频流在Java fx项目上播放。

-- Short version: - 简洁版本:

I'm streaming h264/avcc flavor video from an android phone to a desktop computer. 我正在将h264 / avcc风味视频从Android手机流式传输到台式计算机。 However javafx doesn't have an easy solution for displaying stream. 但是,javafx没有显示流的简单解决方案。 I'm attempting to use javacv / ffmpeg in an attempt to make this work. 我正在尝试使用javacv / ffmpeg来使其正常工作。 However I am getting errors from ffmpeg. 但是我从ffmpeg收到错误。

1) Is there a better way to display streaming video on javafx? 1)有没有更好的方法在javafx上显示流式视频?

2) Do you have a sample project or good tutorial for javacv ffmpegframegrabber? 2)您是否有Javacv ffmpegframegrabber的示例项目或良好教程?

3) I think I may be missing some small detail in mycode but Im not sure what i would be. 3)我想我可能在mycode中缺少一些小细节,但是我不确定我会是什么。

-- Longer Version: -较长版本:

1) On the android end Im getting video using mediarecorder. 1)在Android端,我正在使用mediarecorder获取视频。 In order to get the sps/pps info I record and save a small movie to the device and then parse the sps and pps data. 为了获取sps / pps信息,我记录并保存了一个小电影到设备,然后解析sps和pps数据。

2) Next, on the android, I split up the nalus to meet MTU req and send them over a udp connection to my desktop 2)接下来,在android上,我将nalus拆分成MTU req,并通过udp连接将它们发送到我的桌面

3)On my desktop I reassmble the nalus( or trash them if they loose data) and feed those to an input stream that I gave to the framegreabber constructor. 3)在我的桌面上,我重新组装了nalus(如果它们丢失了数据,则将其丢弃),并将其馈送到我提供给framegreabber构造函数的输入流中。

-- The Code and Logs: -代码和日志:

The errors are long and numerous depending on the flavor I feed it. 根据我所喂食的口味,错误会很长而且很多。 Here are two separate examples which are usually repeated at great length 这是两个单独的示例,通常会重复很长时间

[h264 @ 0000020225907a40] non-existing PPS 0 referenced
[h264 @ 0000020225907a40] decode_slice_header error
[h264 @ 0000020225907a40] no frame!

[h264 @ 00000163d8637a40] illegal aspect ratio
[h264 @ 00000163d8637a40] pps_id 3412 out of range
[AVBSFContext @ 00000163e28a0e00] Invalid NAL unit 0, skipping.

!! One big caveat that I am aware off is that I have not implemented timestamps which I created on the android device when feeding ffmpeg. 我知道的一个重要警告是,我尚未实现在喂入ffmpeg时在android设备上创建的时间戳。 I think it should still show distorted images without this though 我认为尽管如此,它仍然应该显示失真的图像

Because I have spent all day guessing and trying I have several "flavors" of data I have shoved through. 因为我整天都在猜测和尝试,所以我掌握了一些“味道”的数据。 I am only showing the first section of each nal which I believe if correct would at least show a garbage image as long as my sps and pps are right 我只显示每个nal的第一部分,只要我的sps和pps正确,我相信如果正确的话至少会显示垃圾图像。

sps: 67 80 80 1E E9 01 68 22 FD C0 36 85 09 A8
pps: 68 06 06 E2

Below is annex B style. 以下是附件B样式。 These were each prefixed with either 00 00 01 and 00 00 00 01 它们分别以00 00 01和00 00 00 01为前缀

Debug transfer 65 B8 40 0B E5 B8 7B 80 5B 85 
Debug transfer 41 E2 20 7A 74 34 3B D6 BE FA 
Debug transfer 41 E4 40 2F 01 E0 0C 06 EE 91 
Debug transfer 41 E6 60 3E A1 20 5A 02 3C 6D 
Debug transfer 41 E8 80 13 B0 B9 82 C3 03 F4 
Debug transfer 41 EC C0 1B A3 0C 28 F1 B0 C8 
Debug transfer 41 EE E0 1F CE 07 30 EE 05 06 
Debug transfer 41 F1 00 08 ED 80 9C 20 09 73 
Debug transfer 41 F3 20 09 E9 00 86 60 21 C3 
VideoDecoderaddPacket type: 24
Debug transfer 67 80 80 1E E9 01 68 22 FD C0 
Debug transfer 68 06 06 E2 
Debug transfer 65 B8 20 00 9F 80 78 00 12 8A 
Debug transfer 41 E2 20 09 F0 1E 40 7B 0C E0 
Debug transfer 41 E4 40 09 F0 29 30 D6 00 AE 
Debug transfer 41 E6 60 09 F1 48 31 80 99 40 
[h264 @ 000001c771617a40] non-existing PPS 0 referenced

Here I tried Avcc style. 在这里,我尝试了Avcc风格。 You can see the first line is the combination of the sps pps followed by idr and then repeated non idr 您可以看到第一行是sps pps的组合,后跟idr,然后重复出现非idr

Debug transfer 18 00 0E 67 80 80 1E E9 01 68 
Debug transfer 00 02 4A 8F 65 B8 20 00 9F C5 
Debug transfer 00 02 2F DA 41 E2 20 09 E8 0F 
Debug transfer 00 02 2C 34 41 E4 40 09 F4 20 
Debug transfer 00 02 4D 92 41 E6 60 09 FC 2B 
Debug transfer 00 02 47 02 41 E8 80 09 F0 72 
Debug transfer 00 02 52 50 41 EA A0 09 EC 0F 
Debug transfer 00 02 58 8A 41 EC C0 09 FC 6F 
Debug transfer 00 02 55 F9 41 EE E0 09 FC 6E 
Debug transfer 00 02 4D 79 41 F1 00 09 F0 3E 
Debug transfer 00 02 4D B6 41 F3 20 09 E8 64 

The following class is where I try to get javacv/ffmpeg to show the video. 以下类是我尝试获取javacv / ffmpeg来显示视频的地方。 I dont think its an ideal solution and am researching canvasfram as a replacement to the image view. 我认为这不是理想的解决方案,因此正在研究canvas替代图像视图。

    public class ImageDecoder {

    private final static String TAG = "ImageDecoder ";

    private ImageDecoder(){

    }


    public static void streamImageToImageView(
            final ImageView view,
            final InputStream inputStream,
            final String format,
            final int frameRate,
            final int bitrate,
            final String preset,
            final int numBuffers
    )
    {
        System.out.println("Image Decoder Starting...");


        try(    final FrameGrabber grabber = new 
    FFmpegFrameGrabber(inputStream))
        {

            final Java2DFrameConverter converter = new Java2DFrameConverter();

            grabber.setFrameNumber(frameRate);
            grabber.setFormat(format);
            grabber.setVideoBitrate(bitrate);
            grabber.setVideoOption("preset", preset);
            grabber.setNumBuffers(numBuffers);

            System.out.println("Image Decoder waiting on grabber.start...");
            grabber.start();   //---- this call is blocking the loop

            System.out.println("Image Decoder Looping--------------------------- 
   -------- hit stop");
            while(!Thread.interrupted()){
                //System.out.println("Image Decoder Looping");
                final Frame frame = grabber.grab();
                if (frame != null){
                    final BufferedImage bufferedImage = 
    converter.convert(frame);
                    if (bufferedImage != null){

                        Platform.runLater(() -> 
    view.setImage(SwingFXUtils.toFXImage(bufferedImage, null)));
                    }else{
                        System.out.println("no buf im");
                    }
                }else{
                    System.out.println("no fr");
                    Thread.currentThread().interrupt();
                }

            }



        }catch (Exception e){
            System.out.print(TAG + e);
        }


    }






    }

Any help is greatly appreciated. 任何帮助是极大的赞赏。

So I had two problems. 所以我有两个问题。

The first was that my sps pps parsing method had a mistake. 首先是我的sps pps解析方法有错误。 Notice the 2nd and 3rd bytes are same 注意第二和第三字节相同

The second was I accidentally over sized a buffer and created large 0x00 padded areas which emulated start codes. 第二个是我不小心使缓冲区过大,并创建了较大的0x00填充区域来模拟起始代码。

This was a big project for me and I want to help other. 这对我来说是一个很大的项目,我想帮助其他人。 Please visit my website where I wrote a lengthy multi-part discussion about streaming h264 请访问我的网站,在该网站上我写了关于流媒体h264的长时间讨论

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM