繁体   English   中英

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

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

我真的很想让视频流在Java fx项目上播放。

- 简洁版本:

我正在将h264 / avcc风味视频从Android手机流式传输到台式计算机。 但是,javafx没有显示流的简单解决方案。 我正在尝试使用javacv / ffmpeg来使其正常工作。 但是我从ffmpeg收到错误。

1)有没有更好的方法在javafx上显示流式视频?

2)您是否有Javacv ffmpegframegrabber的示例项目或良好教程?

3)我想我可能在mycode中缺少一些小细节,但是我不确定我会是什么。

-较长版本:

1)在Android端,我正在使用mediarecorder获取视频。 为了获取sps / pps信息,我记录并保存了一个小电影到设备,然后解析sps和pps数据。

2)接下来,在android上,我将nalus拆分成MTU req,并通过udp连接将它们发送到我的桌面

3)在我的桌面上,我重新组装了nalus(如果它们丢失了数据,则将其丢弃),并将其馈送到我提供给framegreabber构造函数的输入流中。

-代码和日志:

根据我所喂食的口味,错误会很长而且很多。 这是两个单独的示例,通常会重复很长时间

[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.

我知道的一个重要警告是,我尚未实现在喂入ffmpeg时在android设备上创建的时间戳。 我认为尽管如此,它仍然应该显示失真的图像

因为我整天都在猜测和尝试,所以我掌握了一些“味道”的数据。 我只显示每个nal的第一部分,只要我的sps和pps正确,我相信如果正确的话至少会显示垃圾图像。

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

以下是附件B样式。 它们分别以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

在这里,我尝试了Avcc风格。 您可以看到第一行是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 

以下类是我尝试获取javacv / ffmpeg来显示视频的地方。 我认为这不是理想的解决方案,因此正在研究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);
        }


    }






    }

任何帮助是极大的赞赏。

所以我有两个问题。

首先是我的sps pps解析方法有错误。 注意第二和第三字节相同

第二个是我不小心使缓冲区过大,并创建了较大的0x00填充区域来模拟起始代码。

这对我来说是一个很大的项目,我想帮助其他人。 请访问我的网站,在该网站上我写了关于流媒体h264的长时间讨论

暂无
暂无

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

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