【问题标题】:Webcam capture for opencv in Android ,built with ffmpeg and compiled for androidAndroid中opencv的网络摄像头捕获,用ffmpeg构建并为android编译
【发布时间】:2017-12-15 16:39:03
【问题描述】:

我刚刚购买了一台 onwave ip 摄像头,主要目的是使用 Android 平板电脑进行图像处理和监控。在本机编码以及使用 FFMPEG 为 java、python 和 C++ 交叉编译时。Videocapture 类与 ip camera url 一起工作完美无缺。它显示了使用 rtsp 协议进行流式传输的 ipcamera 的帧。 例如在 C++ 中 `

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

代码完美运行,它为我提供了 LAN 上摄像头流中的帧,几乎没有延迟。python 和 Java 编译时也是如此。

然而,当来到 android 时问题就来了,因为 android 的 opencv sdk 本身并不支持 ffmpeg。起初我不想用 ffmpeg for android 重新编译它,而是选择了 JavaCV,它带有预构建的 ffmpegframegrabber 类并且还保留opencv 的本机源代码。但是当我尝试使用它在位图上显示帧时,framegrabber 失败了,并且丢包存在巨大的渲染问题,并且帧全部乱码,还尝试使用 FrameRecorder 类并在后台记录文件但结果相同。 后来我尝试使用适用于 Android 的 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++ 中一样使用 Android 中的 Videocapture 类,而不使用 NDK?如果有人曾经使用官方 sdk 在带有 ipcam 的 Android 平板电脑和手机上尝试过,那将非常有帮助。或者是否有其他方法可以使用媒体播放器或 JavaCV 让我在没有任何乱码帧的情况下几乎没有延迟

【问题讨论】:

    标签: android opencv android-mediaplayer javacv android-ffmpeg


    【解决方案1】:

    为 ffmpeg 配置你想要的所有东西需要一些时间,虽然我有一段时间没有碰它,也许有些改变了。最好从寻找一个已经集成的 github 项目开始,然后从那里开始,应该有很多这样的项目(找到一个更新的项目)。大约 3 年前,当我在做视频通话时,还没有合适的 Android 媒体 API,目前有低级回调,所以你应该成功实现你想要的任何东西。

    【讨论】:

      【解决方案2】:

      我实际上已经通过从源代码编译用于 android (armhf) 的 opencv 库以及包括 libav、libswsscale 等的 ffmpeg 库来解决了这个问题。比我首先使用 ffmpegs avframe 类捕获帧并将帧转换为 openCV 的 Mat分离pthread并应用所有图像处理算法,最后通过JNI从主程序调用主函数。

      【讨论】:

        猜你喜欢
        • 2015-08-18
        • 2011-02-28
        • 1970-01-01
        • 1970-01-01
        • 2015-01-10
        • 1970-01-01
        • 1970-01-01
        • 2013-06-03
        • 1970-01-01
        相关资源
        最近更新 更多