前天经理交给我一个任务,需求是在一个应用中获取摄像头的数据传递到另外一个应用中使用,生成图片。原理是运用android进程之间的通信AIDL技术,传递分辨率,图片的格式N21,摄像头传递的每一帧的图片大小都是固定的,计算方式为宽*高*单位像素字节,把每一帧图片放入共享内存,在客户端中读取共享内存数据,那么怎么保证一边写一边读,读完之后在写,写完之后在读,这样一步一步进行呢,用锁机制肯定是不行的,因为这属于不同进程了,经理牛人告诉我,用内存中第一位做标志位,默认为0代表可以写,1代表可以读,这样相互标志位的变化,就保障了流程的运行,最后在拿到摄像头数据之后,怎么把它显示出来呢,直接上代码
new YuvImage(readdata, ImageFormat.
NV21, 1920, 1080,
null);
//YuvImage yuvImage = new YuvImage(mBufferBean.mBuffer, ImageFormat.NV21, 1280, 720, null);
// MyLog.d(TAG, "readShareBufferMsg yuvImage:" + yuvImage);
if (yuvImage !=
null) {
new
new
bmp = BitmapFactory.
decodeByteArray(stream.toByteArray(), 0, stream.size());
stream.close();
}
通过自带的YuvImage类,可以转换成bitmap显示出来。
如何操作MemoryFile呢,上代码
/**
* Created by ethanzhang on 2017/5/10.
*/
import
import
import
import
import
/**
* 对memoryFile类的扩展
* 1.从memoryFile对象中获取FileDescriptor,ParcelFileDescriptor
* 2.根据一个FileDescriptor和文件length实例化memoryFile对象
* Created by wuzr on 2016/7/16.
*/
public class
/**
* 创建共享内存对象
*
*
@param
name
描述共享内存文件名称
*
@param
length
用于指定创建多大的共享内存对象
*
@return
MemoryFile 描述共享内存对象
*/
public static MemoryFile createMemoryFile(String name,
int
try
return new
catch
e.printStackTrace();
}
return null;
}
public static MemoryFile openMemoryFile(ParcelFileDescriptor pfd,
int length,
int
if (pfd ==
null) {
throw new IllegalArgumentException(
"ParcelFileDescriptor 不能为空");
}
FileDescriptor fd = pfd.getFileDescriptor();
return
openMemoryFile(fd, length, mode);
}
/**
* 打开共享内存,一般是一个地方创建了一块共享内存
* 另一个地方持有描述这块共享内存的文件描述符,调用
* 此方法即可获得一个描述那块共享内存的MemoryFile
* 对象
*
*
@param
fd
文件描述
*
@param
length
共享内存的大小
*
@param
mode
PROT_READ = 0x1只读方式打开,
* PROT_WRITE = 0x2可写方式打开,
* PROT_WRITE|PROT_READ可读可写方式打开
*
@return
MemoryFile
*/
public static MemoryFile openMemoryFile(FileDescriptor fd,
int length,
int
null;
try
new MemoryFile(
"tem", 1);
memoryFile.close();
class;
null;
Method[] ms = c.getDeclaredMethods();
for (
int i = 0; ms !=
null && i < ms.
length; i++) {
if (ms[i].getName().equals(
"native_mmap")) {
native_mmap = ms[i];
}
}
setField(
"android.os.MemoryFile", memoryFile,
"mFD", fd);
setField(
"android.os.MemoryFile", memoryFile,
"mLength", length);
long address = (
long) ReflectUtil.
invokeMethod(
null, native_mmap, fd, length, mode);
setField(
"android.os.MemoryFile", memoryFile,
"mAddress", address);
catch
e.printStackTrace();
}
return
}
/**
* 获取memoryFile的ParcelFileDescriptor
*
*
@param
memoryFile
描述一块共享内存
*
@return
ParcelFileDescriptor
*/
public static
if (memoryFile ==
null) {
throw new IllegalArgumentException(
"memoryFile 不能为空");
}
ParcelFileDescriptor pfd;
getFileDescriptor(memoryFile);
getInstance(
"android.os.ParcelFileDescriptor", fd);
return
}
/**
* 获取memoryFile的FileDescriptor
*
*
@param
memoryFile
描述一块共享内存
*
@return
这块共享内存对应的文件描述符
*/
public static
if (memoryFile ==
null) {
throw new IllegalArgumentException(
"memoryFile 不能为空");
}
FileDescriptor fd;
invoke(
"android.os.MemoryFile", memoryFile,
"getFileDescriptor");
return
}
package
import
import
import
/**
* Created by ethanzhang on 2017/5/10.
*/
/**
* 反射工具类
* Created by wuzr on 2016/6/27.
*/
public class
/**
* 根据类名,参数实例化对象
*
*
@param
className
类的路径全名
*
@param
params
构造函数需要的参数
*
@return
返回T类型的一个对象
*/
public static
if (className ==
null || className.equals(
"")) {
throw new IllegalArgumentException(
"className 不能为空");
}
try
forName(className);
if (params !=
null) {
int plength = params.
length;
new
for (
int
paramsTypes[i] = params[i].getClass();
}
Constructor constructor = c.getDeclaredConstructor(paramsTypes);
true);
return
}
Constructor constructor = c.getDeclaredConstructor();
true);
return
catch
e.printStackTrace();
}
return null;
}
/**
* 执行instance的方法
*
*
@param
className
类的全名
*
@param
instance
对应的对象,为null时执行类的静态方法
*
@param
methodName
方法名称
*
@param
params
参数
*/
public static
if (className ==
null || className.equals(
"")) {
throw new IllegalArgumentException(
"className 不能为空");
}
if (methodName ==
null || methodName.equals(
"")) {
throw new IllegalArgumentException(
"methodName不能为空");
}
try
forName(className);
if (params !=
null) {
int plength = params.
length;
new
for (
int
paramsTypes[i] = params[i].getClass();
}
Method method = c.getDeclaredMethod(methodName, paramsTypes);
true);
return
}
Method method = c.getDeclaredMethod(methodName);
true);
return
catch
e.printStackTrace();
}
return null;
}
/**
* 执行指定的对方法
*
*
@param
instance
需要执行该方法的对象,为空时,执行静态方法
*
@param
m
需要执行的方法对象
*
@param
params
方法对应的参数
*
@return
方法m执行的返回值
*/
public static
if (m ==
null) {
throw new IllegalArgumentException(
"method 不能为空");
}
true);
try
return
catch
e.printStackTrace();
}
return null;
}
/**
* 取得属性值
*
*
@param
className
类的全名
*
@param
fieldName
属性名
*
@param
instance
对应的对象,为null时取静态变量
*
@return
属性对应的值
*/
public static
if (className ==
null || className.equals(
"")) {
throw new IllegalArgumentException(
"className 不能为空");
}
if (fieldName ==
null || fieldName.equals(
"")) {
throw new IllegalArgumentException(
"fieldName 不能为空");
}
try
forName(className);
Field field = c.getDeclaredField(fieldName);
true);
return
catch
e.printStackTrace();
}
return null;
}
/**
* 设置属性
*
*
@param
className
类的全名
*
@param
fieldName
属性名
*
@param
instance
对应的对象,为null时改变的是静态变量
*
@param
value
值
*/
public static void
if (className ==
null || className.equals(
"")) {
throw new IllegalArgumentException(
"className 不能为空");
}
if (fieldName ==
null || fieldName.equals(
"")) {
throw new IllegalArgumentException(
"fieldName 不能为空");
}
try
forName(className);
Field field = c.getDeclaredField(fieldName);
true);
field.set(instance, value);
catch
e.printStackTrace();
}
}
/**
* 根据方法名,类名,参数获取方法
*
*
@param
className
类名,全名称
*
@param
methodName
方法名
*
@param
paramsType
参数类型列表
*
@return
方法对象
*/
public static
if (className ==
null || className.equals(
"")) {
throw new IllegalArgumentException(
"className 不能为空");
}
if (methodName ==
null || methodName.equals(
"")) {
throw new IllegalArgumentException(
"methodName不能为空");
}
try
forName(className);
return
catch
e.printStackTrace();
}
return null;
}
}
怎么写入标志位:
while (
mStartVideo &&
mMemoryFile !=
null) {
//读取第一个字节,为0可以写,为1可以读
byte[] buffer=
new byte[1];
try
mMemoryFile.readBytes(buffer,0,0,1);
if(buffer[0]==0)
{
if(
YUVQueue.size()>0)
{
mMemoryFile.writeBytes(
new byte[]{1},0,0,1);
byte[] input=
YUVQueue.poll();
try
mMemoryFile.writeBytes(input,0,1,input.
length);
catch
e.printStackTrace();
}
}
}
catch
e.printStackTrace();
}