手机想看rtsp流媒体视频,路由器端口映射该如何设置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手机想看rtsp流媒体视频,路由器端口映射该如何设置相关的知识,希望对你有一定的参考价值。

说详细点,本人小白

  设置方法:

  1、可以进入路由器,既然的手机能连到路由器,那就在路由器里面肯定有IP地址,找到并记下来。

  2、不能看rtsp 协议的流媒体,那有2种可能,要么路由给过滤掉了,要么路由不支持。

  3、可以进入到--转发规则--DMZ主机(这里以TP-LINK无线路由为例)--选择启用--输入手机设备的IP--保存并重启路由。

参考技术A 手机看rtsp视频流是不需要路由器作什么映射,要看路由器是否打开rstp的ALG配置。

如何在 Java 环境中解码 H.264 视频帧

【中文标题】如何在 Java 环境中解码 H.264 视频帧【英文标题】:How to decode H.264 video frame in Java environment 【发布时间】:2011-01-11 01:22:12 【问题描述】:

有谁知道?

我的网络摄像机产品支持 RTP/RTSP 流媒体。

提供来自我的网络摄像机的服务标准 RTP/RTSP,它还支持“RTP/RTSP over HTTP”。

RTSP:TCP 554 RTP 起始端口:UDP 5000

【问题讨论】:

【参考方案1】:

或使用Xuggler。适用于 RTP、RTMP、HTTP 或其他协议,可以对 H264 和大多数其他编解码器进行解码和编码。并且得到积极维护、免费和开源 (LGPL)。

【讨论】:

使用像 Xuggler 这样的非活动项目通常不是一个好主意。我建议找到正在积极开发的东西。 实际上,@ArtClarke 开发了它替代 humble-video :)【参考方案2】:

我发现了一个基于JavaCV's FFmpegFrameGrabber class 的非常简单直接的解决方案。该库允许您通过将 ffmpeg 包装在 Java 中来播放流媒体。

如何使用?

首先,您可以使用 Maven 或 Gradle 下载并安装该库。

这里有一个 StreamingClient 类,它调用了一个具有 Thread 播放视频的 SimplePlayer 类。

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 类使用FFmpegFrameGrabber 解码frame,该frame 被转换为图像并显示在您的舞台中

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();
    

【讨论】:

【参考方案3】:

您可以使用名为 JCodec (http://jcodec.org) 的纯 Java 库。 解码一个 H.264 帧很简单:

ByteBuffer bb = ... // Your frame data is stored in this buffer
H264Decoder decoder = new H264Decoder();
Picture out = Picture.create(1920, 1088, ColorSpace.YUV_420); // Allocate output frame of max size
Picture real = decoder.decodeFrame(bb, out.getData());
BufferedImage bi = JCodecUtil.toBufferedImage(real); // If you prefere AWT image

如果您想从容器(如 MP4)中读取数据,可以使用方便的帮助类 FrameGrab:

int frameNumber = 150;
BufferedImage frame = FrameGrab.getFrame(new File("filename.mp4"), frameNumber);
ImageIO.write(frame, "png", new File("frame_150.png"));

最后,这是一个完整的复杂示例:

private static void avc2png(String in, String out) throws IOException 
    SeekableByteChannel sink = null;
    SeekableByteChannel source = null;
    try 
        source = readableFileChannel(in);
        sink = writableFileChannel(out);

        MP4Demuxer demux = new MP4Demuxer(source);

        H264Decoder decoder = new H264Decoder();

        Transform transform = new Yuv420pToRgb(0, 0);

        MP4DemuxerTrack inTrack = demux.getVideoTrack();

        VideoSampleEntry ine = (VideoSampleEntry) inTrack.getSampleEntries()[0];
        Picture target1 = Picture.create((ine.getWidth() + 15) & ~0xf, (ine.getHeight() + 15) & ~0xf,
                ColorSpace.YUV420);
        Picture rgb = Picture.create(ine.getWidth(), ine.getHeight(), ColorSpace.RGB);
        ByteBuffer _out = ByteBuffer.allocate(ine.getWidth() * ine.getHeight() * 6);
        BufferedImage bi = new BufferedImage(ine.getWidth(), ine.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
        AvcCBox avcC = Box.as(AvcCBox.class, Box.findFirst(ine, LeafBox.class, "avcC"));

        decoder.addSps(avcC.getSpsList());
        decoder.addPps(avcC.getPpsList());

        Packet inFrame;
        int totalFrames = (int) inTrack.getFrameCount();
        for (int i = 0; (inFrame = inTrack.getFrames(1)) != null; i++) 
            ByteBuffer data = inFrame.getData();

            Picture dec = decoder.decodeFrame(splitMOVPacket(data, avcC), target1.getData());
            transform.transform(dec, rgb);
            _out.clear();

            AWTUtil.toBufferedImage(rgb, bi);
            ImageIO.write(bi, "png", new File(format(out, i)));
            if (i % 100 == 0)
                System.out.println((i * 100 / totalFrames) + "%");
        
     finally 
        if (sink != null)
            sink.close();
        if (source != null)
            source.close();
    

【讨论】:

工作太慢,每getFrame()一秒,和你做同样的解码【参考方案4】:

我认为最好的解决方案是使用“JNI + ffmpeg”。在我目前的项目中,我需要在一个基于 libgdx 的 java openGL 游戏中同时播放多个全屏视频。我已经尝试了几乎所有的免费库,但没有一个具有可接受的性能。所以最后我决定编写自己的 jni C 代码来使用 ffmpeg。这是我笔记本电脑上的最终表现:

环境:CPU:Core i7 Q740 @1.73G,视频:nVidia GeForce GT 435M, 操作系统:Windows 7 64bit,Java:Java7u60 64bit 视频:h264rgb / h264 编码,无声音,分辨率:1366 * 768 解决方案:解码:JNI + ffmpeg v2.2.2,上传到GPU: 使用 lwjgl 更新 openGL 纹理 性能:解码速度: 700-800FPS,纹理上传:大约每帧1ms

我只花了几天时间就完成了第一个版本。但是第一版的解码速度只有120FPS左右,上传时间大约是每帧5ms。经过几个月的优化,我得到了这个最终性能和一些附加功能。现在我可以同时播放多个高清视频而不会出现任何缓慢。

我游戏中的大多数视频都有透明背景。这种透明视频是一个mp4文件,有2个视频流,一个流存储h264rgb编码的rgb数据,另一个流存储h264编码的alpha数据。所以要播放 alpha 视频,我需要解码 2 个视频流并将它们合并在一起,然后上传到 GPU。因此,我可以在我的游戏中同时在不透明高清视频上方播放多个透明高清视频。

【讨论】:

我为 android 创建了一个应用程序,它记录来自相机的视频并使用 RTP/RTSP 发送它。我使用MediaRecorder 类来捕获和编码来自摄像机的视频。我使用 VLC 测试了我的实现,它可以工作。我尝试使用接收有效负载96 的Java 创建客户端。我尝试了很多东西,例如 Toolkit 类,但它的方法 createImage(payload, 0, payloadLength) 仅从 byte[] 的有效负载中提取 JPG 或 PNG 我也尝试使用 Xuggler,但我只找到了使用 mp4 文件的示例我需要从byte[] 解码。 (我不知道 C)【参考方案5】:

看看 Java 媒体框架 (JMF) - http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/formats.html

我之前用过它,它有点不成熟,但从那时起他们可能已经加强了它。

【讨论】:

JMF 被遗弃,死了多年。因此,在长期项目中依赖它并不是一个好主意。但如果这是一次性的事情,我同意 JMF 是一个很好的解决方案。虽然我相信 JMF 只支持 H263。 如果JMF死了,可以用什么代替它?

以上是关于手机想看rtsp流媒体视频,路由器端口映射该如何设置的主要内容,如果未能解决你的问题,请参考以下文章

ONVIF协议只能用在局域网?设备提供的web服务、RTSP流地址都是自己的局域网IP地址,手机外网怎么调用?

443端口被封,如何远程调试大华摄像机

网页无插件视频流媒体播放器EasyPlayer-RTSP在WPF框架播放不显示视频画面,该如何排查处理?

RTSP 上音频和视频的相同媒体格式

RTSP视频结构化智能分析平台EasyNVR出现无法播放HLS视频流的问题,该如何排查与解决?

大华视频参数说明