使用 ffmpeg 将低延迟 RTSP 视频流式传输到 android

Posted

技术标签:

【中文标题】使用 ffmpeg 将低延迟 RTSP 视频流式传输到 android【英文标题】:Stream low latency RTSP video to android with ffmpeg 【发布时间】:2014-12-14 21:32:16 【问题描述】:

我正在尝试使用 KitKat 将实时网络摄像头视频从 Ubuntu 12.04 PC 流式传输到 android 设备。到目前为止,我已经编写了 ffserver 配置文件来接收 ffm 提要并通过 rtsp 协议进行广播。我可以用ffplay在同一个局域网的另一台电脑上观看流。

如何在安卓设备上观看直播?当使用 vlc 流式传输网络摄像头图像但不使用 ffmpeg 时,以下代码运行良好:

public class MainActivity extends Activity implements MediaPlayer.OnPreparedListener,
        SurfaceHolder.Callback 

    final static String RTSP_URL = "rtsp://192.168.1.54:4424/test.sdp";

    private MediaPlayer _mediaPlayer;
    private SurfaceHolder _surfaceHolder;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        // Set up a full-screen black window.
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        Window window = getWindow();
        window.setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        window.setBackgroundDrawableResource(android.R.color.black);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_main);

        // Configure the view that renders live video.
        SurfaceView videoView =
                (SurfaceView) findViewById(R.id.videoView); //where R.id.videoView is a simple SurfaceView element in the layout xml file
        _surfaceHolder = videoView.getHolder();
        _surfaceHolder.addCallback(this);
        _surfaceHolder.setFixedSize(320, 240);
    
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) 
        _mediaPlayer = new MediaPlayer();
        _mediaPlayer.setDisplay(_surfaceHolder);
        Context context = getApplicationContext();
        Uri source = Uri.parse(RTSP_URL);
        try 
            // Specify the IP camera's URL and auth headers.
            _mediaPlayer.setDataSource(context, source);

            // Begin the process of setting up a video stream.
            _mediaPlayer.setOnPreparedListener(this);
            _mediaPlayer.prepareAsync();
        
        catch (Exception e) 
    
    @Override
    public void onPrepared(MediaPlayer mediaPlayer) 
        _mediaPlayer.start();
    

我的 ffserver.config 文件:

HTTPPort 8090
RTSPBindAddress 0.0.0.0
RTSPPort 4424
MaxBandwidth 10000
CustomLog -

<Feed feed1.ffm>
        File /tmp/feed1.ffm
        FileMaxSize 20M
        ACL allow 127.0.0.1
</Feed>
<Stream test1.sdp>
    Feed feed1.ffm
    Format rtp  
    VideoCodec libx264
    VideoSize 640x480
    AVOptionVideo flags +global_header
    AVOptionVideo me_range 16
    AVOptionVideo qdiff 4
    AVOptionVideo qmin 10
    AVOptionVideo qmax 51
    Noaudio
    ACL allow localhost
        ACL allow 192.168.0.0 192.168.255.255
</Stream>

我正在使用以下命令启动流:ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -b:v 600k http://localhost:8090/feed1.ffm

【问题讨论】:

也许使用 Wireshark 检查 RTSP 级别发生的情况 - 连接是否打开,是否找到轨道?如果未找到该轨道,则问题很可能出在 ffserver 上,否则如果推送数据,则可能存在 Android 无法处理的格式问题。 我检查了 android here 支持的格式,我正在使用支持的格式。我也确信连接是由ffserver打开和注册的。控制台输出:Mon Oct 20 17:04:53 2014 192.168.1.55 - - [DESCRIBE] "rtsp://192.168.1.54:4424/test.sdp RTSP/1.0" 200 72 Android Studio 中的 logcat 显示以下错误 MediaPlayer: Error (1,-2147483648),这是未知的(描述为here) 你提到的帖子包含这个07-18 13:47:14.245: W/QCvdec(68): Parsing Error unsupported profile or level - 你也有这个吗? libx264 可能正在使用不受支持的压缩参数,而 vlc 可能正在使用受支持的压缩参数。 不,我没有。我只有D/MediaPlayer﹕ Couldn't open file on client side, trying server side W/MediaPlayer﹕ info/warning (701, 0) E/MediaPlayer﹕ error (1, -2147483648) 【参考方案1】:

此错误很可能是由 VLC 和 FFmpeg 的不同编码参数引起的 - VLC 可以使用 Android 能够支持的编码参数,但 FFmpeg 可能使用不受支持的参数(很可能是 AVC 配置文件和级别)。尝试通过 FFmpeg 命令行选项和 ffserver.config 强制基线或主配置文件和 YUV 4:2:0 像素格式。

【讨论】:

以上是关于使用 ffmpeg 将低延迟 RTSP 视频流式传输到 android的主要内容,如果未能解决你的问题,请参考以下文章

从rtsp流式传输视频,帧速率为1 fps

从 FFmpeg 流式传输 RTSP 需要哪些步骤?

使用 FFMPEG 库接收 RTSP 流

使用 ffmpeg 从 C++ 内存中的多个图像流式传输 RTSP

FFmpeg 代码实现流媒体推流(RTSP)

流式 RTSP(AspNet 5 API、FFMPEG、Angular 10、videoJs)[已解决]