1 JavaCV1.3.3下载地址:
JavaCV1.3.3
VLC搭建RTSP视频流,用于测试Android程序是否可以正常获取视频数据
VLC搭建RTSP视频流服务
2 解压缩下载的文件
3 新建Android Studio工程
在lib目录中添加如下jar
ffmpeg.jar
ffmpeg-android-arm.jar
javacpp.jar
javacv.jar
opencv.jar
opencv-android-arm.jar
4 在app上点击右键–>”Open Module Settings”(或者按F4按键)
进入“Dependencies”点击“+”号添加lib中对应的jar文件
5 在build.gradle(Module:app)中添加
packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor'
pickFirst 'META-INF/maven/org.bytedeco.javacpp-presets/opencv/pom.properties'
pickFirst 'META-INF/maven/org.bytedeco.javacpp-presets/opencv/pom.xml'
pickFirst 'META-INF/maven/org.bytedeco.javacpp-presets/ffmpeg/pom.properties'
pickFirst 'META-INF/maven/org.bytedeco.javacpp-presets/ffmpeg/pom.xml'
}
6 至此,javaCV已添加到Android Studio工程中。
7 测试
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.xaeel.javacvtest.MainActivity">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<ImageView
android:id="@+id/img1"
android:layout_width="368dp"
android:layout_height="232dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="29dp" />
</android.support.constraint.ConstraintLayout>
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.Menu;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.VideoView;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.AndroidFrameConverter;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import java.io.File;
import java.util.Date;
import static org.bytedeco.javacpp.opencv_core.IPL_DEPTH_8U;
public class MainActivity extends AppCompatActivity {
private SurfaceView videoSurface = null;
private RecorderManager recorderManager = null;
CameraManager cameraManager;
private ProgressView progressView = null;
private VideoView videoView = null;
private boolean isPlaying = false;
// private TextView sign;
private Runnable progressRunnable = null;
private View finishView = null;
private Button finishButton = null;
private Button swithButton = null;
//Handler handler = null;
ImageView imageView;
TextView text1;
AndroidFrameConverter convertToBitmap = new AndroidFrameConverter();
FFmpegFrameGrabber grabber = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text1 = (TextView)findViewById(R.id.text1);
imageView = (ImageView) findViewById(R.id.img1);
// 测试读取图片
//Drawable drawable = idToDrawable(R.mipmap.ic_launcher);
// Bitmap bitmap = this.drawableToBitmap(drawable);
// Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
// IplImage iplImage = this.bitmapToIplImage(bitmap);
// // 反转图像
// cvFlip(iplImage,iplImage,0);
// bitmap = this.IplImageToBitmap(iplImage);
// imageView.setImageBitmap(bitmap);
// 测试获取视频流并截取其中一张图片
// 其中视频流可以自己在VLC中搭建
grabber = new FFmpegFrameGrabber("rtmp://XXX.XXX.XXX.XXX:1935/live/test.stream");
Bitmap bitmap = null;
if (start(grabber)) {
text1.setText("start(grabber)");
Frame img = null;
try {
img = grabber.grabImage();
if (img != null) {
bitmap = convertToBitmap.convert(img);
imageView.setImageBitmap(bitmap);
//frame.showImage(img);
if (img.keyFrame) {
text1.setText("关键帧:");
//System.err.println("关键帧:" + img.image);
} else {
text1.setText("not 关键帧:");
}
} else {
text1.setText("没有帧:");
//System.err.println("没有帧");
}
Thread.sleep(40);
} catch (Exception e) {
text1.setText("丢帧:");
//System.err.println("丢帧");
}
} else {
text1.setText("不能打开视频流");
}
stop(grabber);
text1.setText("结束视频流");
}
/**
* IplImage转化为Bitmap
* @param iplImage
* @return
*/
public Bitmap IplImageToBitmap(opencv_core.IplImage iplImage) {
Bitmap bitmap = null;
bitmap = Bitmap.createBitmap(iplImage.width(), iplImage.height(),
Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(iplImage.getByteBuffer());
return bitmap;
}
/**
* Bitmap转化为IplImage
* @param bitmap
* @return
*/
public opencv_core.IplImage bitmapToIplImage(Bitmap bitmap) {
opencv_core.IplImage iplImage;
iplImage = IplImage.create(bitmap.getWidth(), bitmap.getHeight(),
IPL_DEPTH_8U, 4);
bitmap.copyPixelsToBuffer(iplImage.getByteBuffer());
return iplImage;
}
/**
* 将资源ID转化为Drawable
* @param id
* @return
*/
public Drawable idToDrawable(int id) {
return this.getResources().getDrawable(id);
}
/**
* 将Drawable转化为Bitmap
* @param drawable
* @return
*/
public Bitmap drawableToBitmap(Drawable drawable) {
if(drawable == null)
return null;
return ((BitmapDrawable)drawable).getBitmap();
}
public static boolean start(FrameGrabber grabber) {
try {
grabber.start();
return true;
} catch (org.bytedeco.javacv.FrameGrabber.Exception e2) {
System.err.println("第一次打开失败,重新开始");
try {
grabber.restart();
return true;
} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
try {
System.err.println("重启抓取器失败,正在关闭抓取器...");
grabber.stop();
} catch (org.bytedeco.javacv.FrameGrabber.Exception e1) {
System.err.println("停止抓取器失败!");
}
}
}
return false;
}
public static boolean stop(FrameGrabber grabber) {
try {
grabber.flush();
grabber.stop();
return true;
} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
return false;
} finally {
try {
grabber.stop();
} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
System.err.println("关闭抓取器失败");
}
}
}