Я только что купил ip-камеру onwave, основной целью было выполнять обработку и мониторинг изображений с помощью планшета Android. При кодировании изначально и при кросс-компиляции для java, python и C ++ с FFMPEG. Класс Videocapture работает с URL-адресом ip-камеры работает безупречно. Он показывает кадры ip-камеры, которая использует протокол rtsp для потоковой передачи. например, в С++ `
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. Однако фреймграббер подвел меня, когда я попытался показать кадры на растровом изображении, и возникла огромная проблема с рендерингом с потерей пакетов, и кадр был искажен, также пробовал с классом FrameRecorder и записывал файл в фоновом режиме, но с тем же результат. Позже я попытался использовать медиаплеер для 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 и телефонах с ip-камерой, используя официальный sdk. Или есть ли другой способ, используя медиаплеер или JavaCV, который дает мне небольшую задержку или не дает никаких искаженных кадров?