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