当前位置: 首页 > 知识库问答 >
问题:

Android中opencv的网络摄像头捕获,用ffmpeg构建,并为Android编译

鄂伟兆
2023-03-14

我刚买了一台onwave ip相机,主要目的是使用Android Tablet进行图像处理和监控。在本机编码的同时,用FFMPEG对java、python和C++进行交叉编译。Videocapture类与ip相机的url配合工作非常完美。它显示了使用rtsp协议进行流的ipcamera的帧。例如在C++中

       Mat frame
        Videocapture cap;
         cap.open(rtsp:// the url);
           while(true)
           {
               cap.read(frame);
               waitkey(1);
            } 

代码工作得很好,它给了我局域网上相机流的帧,几乎没有延迟。对于python和对于Java编译时也是如此。

但是问题来了,因为android的opencv sdk原生支持ffmpeg,一开始我不想用android的ffmpeg重新编译它,而是选择了JavaCV,它带有预构建的ffmpegframegrabber类,还保留了opencv的原生源代码。然而,framegrabber失败了,当我尝试用位图显示帧时,有很大的数据包丢失和帧乱码的渲染问题,也尝试用FrameRecorder类,在后台记录文件,但结果相同。后来我尝试使用Android的Mediaplayer。附件是我使用Mediaplayer的代码。

    package com.example.rob.androidipcamera4;

   import android.app.Activity;
   import android.content.Context;
   import android.media.MediaPlayer;
   import android.net.Uri;
   import android.support.v7.app.AppCompatActivity;
   import android.os.Bundle;
   import android.util.Base64;
   import android.view.SurfaceHolder;
   import android.view.SurfaceView;
   import android.view.Window;
   import android.view.WindowManager;


  import java.io.IOException;
  import java.util.HashMap;
  import java.util.Map;

  public class MainActivity extends Activity implements        MediaPlayer.OnPreparedListener,SurfaceHolder.Callback {
final static String RTSP_URL="rtsp://192.168.1.7:554/onvif1";
private static String USERNAME="";
private static String PASSWORD="";
private MediaPlayer mediaplayer;
private  SurfaceHolder surfaceholder;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    Window window=getWindow();
    window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    window.setBackgroundDrawableResource(android.R.color.black);
    setContentView(R.layout.activity_main);
    //Configuring the surfaceview
    SurfaceView surfaceView=(SurfaceView)findViewById(R.id.surfaceView);
    surfaceholder = surfaceView.getHolder();
    surfaceholder.addCallback(this);
    surfaceholder.setFixedSize(320,320);
}

@Override
public void onPrepared(MediaPlayer mp) {
    mediaplayer.start();

}

@Override
public void surfaceCreated(SurfaceHolder sh)  {
    mediaplayer=new MediaPlayer();
    mediaplayer.setDisplay(surfaceholder);
    Context context=getApplicationContext();
    Map<String,String>headers=getRTSPHeaders();
    Uri source=Uri.parse(RTSP_URL);
    try{
        mediaplayer.setDataSource(context,source,headers);
        mediaplayer.setOnPreparedListener(this);
        mediaplayer.prepareAsync();
    }
    catch (Exception e){
        System.out.println("Sorry no media ");
    };
   }

@Override
public void surfaceChanged(SurfaceHolder sh, int f, int w, int h) {}

@Override
public void surfaceDestroyed(SurfaceHolder sh) {
    mediaplayer.release();

}
private  Map<String,String>getRTSPHeaders() {
    Map<String,String>headers=new HashMap<String, String>();
    String basicAuthValue=getBasicAuthValue(USERNAME,PASSWORD);
    headers.put("Authorisation",basicAuthValue);
    return headers;
}
private String getBasicAuthValue(String usr,String pwd){
    String credientials=usr+":"+pwd;
    int flags= Base64.URL_SAFE|Base64.NO_WRAP;
    byte[]bytes=credientials.getBytes();
    return "Basic" + Base64.encodeToString(bytes,flags) ;

}
}

虽然帧的分辨率很好,也给了我一个选择,采取每一帧和做一些运动检测,但有大约7秒的延迟在现场流,这是完全不能接受的监测。

所以我想我又回到了为android编译ffmpeg的起点。我只是有疑问,因为用opencv编译的ffmpeg在C++和Python(在linux上)中完美无缺地工作了0.2秒,用android编译ffmpeg是否会给我同样的结果,我是否可以像在C++中那样使用Videocapture类,而不使用NDK?如果有人曾经使用官方SDK在Android平板电脑和带有ipcam的手机上尝试过这一点,那将是非常有帮助的。或者,是否有其他方法可以使用mediaplayer或JavaCV,让我在没有任何乱码帧的情况下轻松或没有延迟

共有1个答案

洪弘壮
2023-03-14

为ffmpeg配置您想要的一切需要一些时间,尽管我有一段时间没有接触它,也许有些东西改变了。更好的开始是寻找一个已经集成了它的github项目,从这个开始,应该有很多他们躺在周围(找一个最近的)。当我做视频通话的时候,大约三年前,没有合适的Android媒体API,目前有低级回调,所以你应该成功地实现你想要的任何东西。

 类似资料:
  • 我目前正在做一个项目,从网络摄像头捕捉视频,并通过UDP发送编码流来做实时流。 有人说从cap.read得到的帧已经是解码帧,我不知道这是如何以及何时发生的。我想要的是编码的帧或流。我应该怎么做才能得到它?我应该再编码一次吗?

  • 问题内容: 如何连续从摄像头捕获图像? 我想尝试对象识别(也许使用Java Media Framework)。 我当时正在考虑创建两个线程 一个线程: 节点1:捕获实时图像 节点2:将图片另存为“ 1.jpg” 节点3:等待5秒 节点4:重复… 其他线程: 节点1:等到捕获图像 节点2:使用“ 1.jpg”获取每个像素的颜色 节点3:将数据保存在数组中 节点4:重复… 问题答案: 此JavaCV实

  • 本文向大家介绍FFmpeg获取网络摄像头数据解码,包括了FFmpeg获取网络摄像头数据解码的使用技巧和注意事项,需要的朋友参考一下 对USB摄像头实时编码,在前面已经探讨过了。这次改变下思路,尝试去截取网络摄像头的H264码流,将其解码播放。 这里的测试代码,是在海康摄像头的基础上进行的。 解码的大致流程和以前的保持一致,只不过增加了部分函数。 FFmpeg打开媒体文件并查看媒体文件的信息,有三个

  • OpenCV无法在Linux上打开超过8个网络摄像头的视频捕获。这里有一个简单的例子: 对于我的设置(OpenCV 2.4.11,Ubuntu 14.04),比如说,有9个网络摄像头,opencap。py在前8个摄像头(0-7个)中成功,但在最后一个摄像头中成功 注意:正确列出了9个网络摄像头(/dev/video0、/dev/video8)。

  • 我计划用网络摄像机捕捉视频,然后用opencv处理,最后在google原生客户端环境下用opencv naclport在网页上显示输出 我现在意识到的是 使用javascript中的MediaStreamTrack接口和 然后 将其编码为Base64字符串并发送到c模块以使用opencv进行处理, 在cpp模块中,将其解码回Mat图像并进行处理,最后将其发送回浏览器进行显示。 所以我想知道,在op

  • 问题内容: 我一直在尝试使用Python创建一个简单的程序,该程序使用OpenCV从我的网络摄像头获取视频供稿并将其显示在屏幕上。 我知道我之所以在这里,是因为创建了窗口,并且网络摄像头上的灯闪烁了,但是它似乎在窗口中什么都没有显示。希望有人可以解释我在做什么错。 在不相关的注释上,我注意到我的网络摄像头有时会在中更改其索引号,有时我需要输入0、1或2,即使我只连接了一个摄像头,也没有拔下插头(我