Захват веб-камеры для opencv в Android, построенный с помощью ffmpeg и скомпилированный для Android

Я только что приобрел IP-камеру onwave, основная цель заключалась в том, чтобы выполнять обработку и мониторинг изображений с помощью планшета Android. Во время написания кода и при перекрестной компиляции для java, python и C++ с FFMPEG . Класс Videocapture работает с URL-адресом ip-камеры и работает безупречно. Это показывает кадры ipcamera, который использует протокол RTSP для потоковой передачи. например, в C++

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

Код работает безупречно, он дает мне кадры из потока камеры в моей локальной сети практически без задержки. То же самое для python и при компиляции для Java.

Однако проблема возникает при переходе на Android, так как opencv sdk для android изначально не поддерживает ffmpeg. Сначала я не хотел сначала скомпилировать его с ffmpeg для android, а вместо этого пошел на JavaCV, который поставляется с предварительно собранным классом ffmpegframegrabber, а также сохраняет собственный исходный код. коды opencv. Однако framegrabber не помог мне, когда я попытался показать кадры на растровом изображении, и возникла огромная проблема с рендерингом с потерей пакетов, а кадр оказался искаженным, также попытался с классом FrameRecorder и записал файл в фоновом режиме, но с тем же результат. Позже я попытался с помощью Mediaplayer для Android. Прикреплен мой код с помощью медиаплеера.

    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 секунд, что совершенно неприемлемо для мониторинга.

Так что я думаю, что вернулся к исходной точке с компиляцией ffmpeg для android. У меня просто есть сомнения, так как ffmpeg, скомпилированный с opencv, работал безупречно в C++ и Python(в linux), давая мне задержку в 0,2 секунды, даст ли мне компиляция ffmpeg с android тот же результат и могу ли я использовать класс Videocapture в Android так же, как я сделал для C++, без использования NDK? Было бы очень полезно, если бы кто-нибудь когда-либо пробовал это на планшетах Android и телефонах с ipcam, используя официальный sdk. Или есть другой способ использования медиаплеера или JavaCV, который дает мне возможность без задержек без искаженных кадров

2 ответа

Я на самом деле решил эту проблему, скомпилировав библиотеки opencv для android (armhf) из исходного кода, а также библиотеки ffmpeg, которые включают libav, libswsscale и т. д. Затем я сначала захватил кадры с помощью классов ffmpegs avframe и преобразовал кадр в Mat OpenCV в отдельном pthread и применил все алгоритмы обработки изображений, прежде чем, наконец, вызвать основную функцию из основной программы через JNI.

Потребуется некоторое время, чтобы настроить все, что вы хотите для ffmpeg, хотя я некоторое время не трогал его, возможно, что-то изменилось. Лучше начать с поиска проекта github, в котором он уже интегрирован, и начать с него, их должно быть много (найдите более свежий). Когда я работал над видеозвонками, около 3 лет назад, не было соответствующего Android Media API, в настоящее время существуют низкоуровневые обратные вызовы, поэтому вы должны успешно реализовать все, что захотите.

Другие вопросы по тегам