0

我刚刚购买了一台 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);
            } 

该代码完美无缺,它为我提供了局域网上摄像机流中的帧,几乎没有延迟。python 和为 Java 编译时也是如此。

然而,当来到android时问题就来了,因为android的opencv sdk本身并不支持ffmpeg。起初我不想用ffmpeg for android重新编译它,而是选择了JavaCV,它带有预构建的ffmpegframegrabber类并且还保留了本机源代码opencv 的代码。但是当我尝试它时,我无法使用帧抓取器在位图上显示帧,并且存在丢包的巨大渲染问题,并且帧都出现乱码,还尝试使用 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 让我几乎没有延迟或没有任何乱码帧

4

2 回答 2

0

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

于 2018-03-07T05:31:29.340 回答
0

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

于 2017-07-11T15:09:07.573 回答