您的位置:首页 > 移动开发 > Android开发

android视频和音频采集及预览

2016-09-29 14:49 323 查看
android视频和音频采集及预览

本文说明android采集方面的方法,预览用previcw,视频采集用Camera类,音频采集用AudioRecord,如果需要ios采集在我的博客中看上一篇,ffmpeg的windows和linux采集用的dshow,vfw,linux4video,在适合的时候写篇博客。

本文所需代码如下:

package com.android.lvs.lvs_android_device_camera_module;
/**
* Created by zhuweigang on 2016/6/30.
*/

//包含传出的结构体info类
import com.android.lvs.lvsandroidinfo.LvsAndroidInfo;

import android.graphics.ImageFormat;
import android.hardware.Camera;
import java.io.IOException;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.HashMap;
import android.content.Context;
import android.util.AttributeSet;

public class LvsAndroidDeviceCameraPreview extends SurfaceView implements SurfaceHolder.Callback
{
private static final String TAG = "lvs_Camera";
public SurfaceHolder mSurfaceHolder = null;
public Camera mcamera = null;

public LvsAndroidDeviceCameraPreview(Context context)
{
super(context);
}

public LvsAndroidDeviceCameraPreview(Context context, AttributeSet attrs)
{
super(context, attrs);
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder)
{
mSurfaceHolder = surfaceHolder;
if (mcamera != null)
{
//摄像头旋转90度
mcamera.setDisplayOrientation(90);
//设置渲染Holder
try
{
if (mSurfaceHolder != null)
{
mcamera.setPreviewDisplay(mSurfaceHolder);
}
}
catch (IOException exception)
{
}

//开始输出数据
mcamera.startPreview();
}
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2)
{
}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder)
{
mSurfaceHolder = null;
}

public void setCamera(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,Camera> list_Camera,int streamid_accumulation)
{
for (int i = 0; i < list_Module_Info.size();i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + streamid_accumulation);
Camera camera = list_Camera.get(i + streamid_accumulation);
//如果需要采集
if(Module_Info.Is_ToNext_Module == 1)
{
//这里如果多个摄像头同时渲染则需要创建多个渲染对象
mcamera = camera;
Camera.Parameters parameters = camera.getParameters();// 摄像头参数集
parameters.setRotation(90);
parameters.setPreviewFormat(ImageFormat.NV21);
parameters.setPreviewSize(640,480);
}
}
}
}


package com.android.lvs.lvs_android_device_camera_module;
/**
* Created by zhuweigang on 2016/7/1.
*/

//包含传出的结构体info类
import com.android.lvs.lvsandroidinfo.LvsAndroidInfo;

import android.graphics.ImageFormat;
import android.os.Bundle;
import android.hardware.Camera;
import android.os.Bundle;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Date;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import java.io.IOException;
import java.util.concurrent.locks.Lock;

public class LvsAndroidDeviceCameraCollection
{
//成员
private static final String TAG = "lvs_Camera";
public int m_num_device = 0;
public LvsAndroidInfo m_Module_Info = null; //如果多个摄像头得到当前使用的info
int m_streamid_accumulation = 0; //streamid累加,用于区分streamid,当音视频streamid相同时
Lock m_thread_video_callback_lock; //用于视频采集的锁,防止回调取出数据和处理冲突

File file_video = null; //测试采集到的视频数据是否正确
FileOutputStream fos_video = null; //测试采集到的视频数据是否正确

//android 后面的摄像头
public final Camera.PreviewCallback mPreviewCallbacx_CAMERA_FACING_BACK = new Camera.PreviewCallback()
{
@Override
public void onPreviewFrame(byte[] arg0, Camera ncamera)
{
Camera.Parameters parameters = ncamera.getParameters();

if (m_Module_Info != null)
{
//线程锁
m_thread_video_callback_lock.lock();
//回调这一帧的时间戳
long timenow = System.currentTimeMillis();
m_Module_Info.setBuf(arg0);
//for(int p=0;p<arg0.length;p++){
// m_Module_Info.Buf[p]= (char)arg0[p];
//}
m_Module_Info.ActualLen = arg0.length;
m_Module_Info.pts = timenow;
m_Module_Info.dts = timenow;
//释放线程锁
m_thread_video_callback_lock.unlock();
}
}
};

//android 前面的摄像头
public final Camera.PreviewCallback mPreviewCallbacx_CAMERA_FACING_FRONT = new Camera.PreviewCallback()
{
@Override
public void onPreviewFrame(byte[] arg0, Camera ncamera)
{
Camera.Parameters parameters = ncamera.getParameters();

if (m_Module_Info != null)
{
//线程锁
m_thread_video_callback_lock.lock();
//回调这一帧的时间戳
long timenow = System.currentTimeMillis();
m_Module_Info.setBuf(arg0);
//for(int p=0;p<arg0.length;p++){
// m_Module_Info.Buf[p]= arg0[p];
//}
m_Module_Info.ActualLen = arg0.length;
m_Module_Info.pts = timenow;
m_Module_Info.dts = timenow;
//释放线程锁
m_thread_video_callback_lock.unlock();

//测试采集到的视频数据是否正确
/*
if (file_video == null )
{
file_video = new File(Environment.getExternalStorageDirectory() + File.separator + "lvs_test_camera.yuv");
try
{
fos_video = new FileOutputStream(file_video);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//写到文件中
try {
fos_video.write(m_Module_Info.Buf, 0, (int) m_Module_Info.ActualLen);
} catch (IOException e) {
e.printStackTrace();
}
*/
}
}
};

//函数
public int init_param(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,Camera> list_Camera,
int streamid_accumulation,Lock thread_video_callback_lock)
{
int ret = 0;

m_thread_video_callback_lock = thread_video_callback_lock;
m_streamid_accumulation = streamid_accumulation;
m_num_device = Camera.getNumberOfCameras();
for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = new LvsAndroidInfo();
Camera camera = null;
Module_Info.stream_id = i + streamid_accumulation;
Module_Info.Is_ToNext_Module = 1;
Module_Info.device_type = 0; //摄像头
Module_Info.CodecType = 0x1; //视频
Module_Info.pts = 0;
Module_Info.dts = 0;
Module_Info.timebase_num = 1;
Module_Info.timebase_den = 1000; //毫秒转换为妙用
camera = open_camera(Module_Info,i);
if (camera == null)
{
return -1;
}

Module_Info.BufLen = Module_Info.Width *Module_Info.Height*3;
Module_Info.Buf = new byte[Module_Info.Width *Module_Info.Height*3];
Module_Info.ActualLen = 0;

//关闭摄像头 在read/write的时候重新打开
if (camera != null)
{
camera.setPreviewCallback(null); //这里如果不设置会出现崩溃的问题
camera.release();
camera = null;
}
//填写到list中
list_Module_Info.put(i + m_streamid_accumulation,Module_Info);
list_Camera.put(i + m_streamid_accumulation,camera);
}
return 1;
}

public void uninit(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,Camera> list_Camera,Lock thread_video_callback_lock)
{
m_Module_Info = null;

for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + m_streamid_accumulation);
Camera camera = list_Camera.get(i + m_streamid_accumulation);

if (camera != null)
{
//停止输出数据
camera.stopPreview();
camera.setPreviewCallback(null); //这里如果不设置会出现崩溃的问题
//关闭摄像头
camera.release();
camera = null;
}

if (Module_Info != null)
{
if (Module_Info.Buf != null)
{
Module_Info.Buf = null;
}
Module_Info = null;
}
}

list_Module_Info.clear();
list_Module_Info = null;
list_Camera.clear();
list_Camera = null;

m_thread_video_callback_lock = thread_video_callback_lock;
}

public int CameraRead(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,Camera> list_Camera)
{
int ret = 0;

for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + m_streamid_accumulation);
Camera camera = list_Camera.get(i + m_streamid_accumulation);
//如果需要采集
if(Module_Info.Is_ToNext_Module == 1)
{
if (camera == null)
{
camera = open_camera(Module_Info,i);
if (camera == null)
{
return -1;
}

//设置回调函数
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(i,cameraInfo);
if (cameraInfo.facing == cameraInfo.CAMERA_FACING_BACK)
{
camera.setPreviewCallback(mPreviewCallbacx_CAMERA_FACING_BACK);
}
else if(cameraInfo.facing == cameraInfo.CAMERA_FACING_FRONT)
{
camera.setPreviewCallback(mPreviewCallbacx_CAMERA_FACING_FRONT);
}
else
{
return -1;
}

list_Camera.put(i + m_streamid_accumulation,camera);

//得到当前使用的module info
m_Module_Info = Module_Info;

//输出数据在预览类里面做
}
}
}
return 1;
}

public int CameraWrite(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,Camera> list_Camera)
{
int ret = 0;

for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + m_streamid_accumulation);
Camera camera = list_Camera.get(i + m_streamid_accumulation);
//如果需要采集
if(Module_Info.Is_ToNext_Module == 1)
{
if (camera == null)
{
camera = open_camera(Module_Info,i);
if (camera == null)
{
return -1;
}

//设置回调函数
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(i,cameraInfo);
if (cameraInfo.facing == cameraInfo.CAMERA_FACING_BACK)
{
camera.setPreviewCallback(mPreviewCallbacx_CAMERA_FACING_BACK);
}
else if(cameraInfo.facing == cameraInfo.CAMERA_FACING_FRONT)
{
camera.setPreviewCallback(mPreviewCallbacx_CAMERA_FACING_FRONT);
}
else
{
return -1;
}

list_Camera.put(i + m_streamid_accumulation,camera);

//得到当前使用的module info
m_Module_Info = Module_Info;

//输出数据在预览类里面做
}
}
}
return 1;
}

//打开摄像头
private Camera open_camera(LvsAndroidInfo Module_Info,int cameraId)
{
int k = 0;
int m = 0;
//打开摄像头
Camera camera = null;
camera = Camera.open(cameraId);

//重试三次
for(int retry = 0;retry < 3 ;retry ++)
{
if (camera == null)
{
return null;
}
}

//参考SDK中的API,获取摄像头的参数:
Camera.Parameters parameters = camera.getParameters();// 摄像头参数集

//获取摄像头支持的各种格式
List<Integer> supportedPictureFormats = parameters.getSupportedPictureFormats();;
//获取预览的各种视频格式
List<Integer> supportedPreviewFormats = parameters.getSupportedPreviewFormats();
//获取摄像头支持的各种分辨率
List<Camera.Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
//获取预览的各种分辨率
List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
//获取预览摄像头支持的帧率
List<int[]> SupportedPreviewFpsRange = parameters.getSupportedPreviewFpsRange();

// 设置预浏格式,注意要在预览支持的范围内选择
//parameters.setPreviewFormat(ImageFormat.NV21);
// 设置预浏尺寸,注意要在预览支持的范围内选择
//parameters.setPreviewSize(640, 480);

//设置参数
// 设置视频格式 picture是拍照,Preview是视频
parameters.setPreviewFormat(ImageFormat.NV21); //貌似nv21所有手机都支持
Module_Info.Stream_PixFormat = 24;

// 设置照片分辨率,注意要在摄像头支持的范围内选择
Camera.Size camerasize;
for (k = 0; k < supportedPictureSizes.size() ; k++)
{
camerasize = supportedPictureSizes.get(k);
if (camerasize.width == 640 && camerasize.height == 480) //采集默认640 * 480
{
parameters.setPictureSize(640,480);
parameters.setPreviewSize(640,480);
Module_Info.Width = 640;
Module_Info.Height = 480;
break;
}
}
//如果未找到,取出第一个和最后一个用小的
if (k == supportedPictureSizes.size() )
{
//取出第一个
Camera.Size camerasize_first = supportedPictureSizes.get(0);
//取出最后一个
Camera.Size camerasize_end = supportedPictureSizes.get(supportedPictureFormats.size() - 1);
if (camerasize_first.width >= camerasize_end.width)
{
parameters.setPictureSize(camerasize_end.width,camerasize_end.height);
Module_Info.Width = camerasize_end.width;
Module_Info.Height = camerasize_end.height;
}
else
{
parameters.setPictureSize(camerasize_first.width,camerasize_first.height);
Module_Info.Width = camerasize_first.width;
Module_Info.Height = camerasize_first.height;
}
}

// 设置照片帧率,注意要在摄像头支持的范围内选择,如果不支持25fps 直接用默认
List<int[]> PreviewFpsRang = parameters.getSupportedPreviewFpsRange();
int[] FpsRang;
for (m = 0; m< PreviewFpsRang.size();m++)
{
FpsRang = PreviewFpsRang.get(m);
int FpsRangfirst = FpsRang[0];
int FpsRangend = FpsRang[FpsRang.length -1];
if ((FpsRangfirst < 25000 && FpsRangend >= 25000) ||
(FpsRangfirst >= 25000 && FpsRangend < 25000))
{
parameters.setPreviewFpsRange(25000,FpsRangend);
break;
}
else
{
continue;
}
}

//parameters.setRotation(0);
// 设置摄像头参数
camera.setParameters(parameters); //旋转90度,貌似没用
//camera.setDisplayOrientation(0); //旋转90度,貌似没用
return camera;
}
}


package com.android.lvs.lvs_android_device_microphone_module;

/**
* Created by zhuweigang on 2016/7/4.
*/

//包含传出的结构体info类
import android.hardware.Camera;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Xml;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import android.util.Xml.Encoding;

import com.android.lvs.lvsandroidinfo.LvsAndroidInfo;

public class LvsAndroidDeviceMicrophoneCollection
{
private static final String TAG = "lvs_Microphone";
public  int m_num_device = 0;
int frequency = 44100;                                          //采样率
int channelConfig = AudioFormat.CHANNEL_IN_STEREO;          //声道
int audioEncording = AudioFormat.ENCODING_PCM_16BIT;       //样本
AudioRecord m_audioRecord = null;                             //声音采集类,当前使用的麦克风
int m_bufferSize = 0;                                         //声音回调数据buf长度
int m_streamid_accumulation = 0;                            //streamid累加,用于区分streamid,当音视频streamid相同时

//函数
public int init_param(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,AudioRecord> list_AudioRecord,int streamid_accumulation)
{
int ret = 0;
m_streamid_accumulation = streamid_accumulation;

//目前的android手机只有一个麦克风
m_num_device = 1;

for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = new LvsAndroidInfo();
Camera camera = null;
Module_Info.stream_id = i + streamid_accumulation;
Module_Info.Is_ToNext_Module = 1;
Module_Info.device_type = 1;       //麦克风
Module_Info.CodecType = 0x10;      //音频
Module_Info.pts = 0;
Module_Info.dts  = 0;
Module_Info.timebase_num = 1;
Module_Info.timebase_den = 1000;  //毫秒转换为妙用
Module_Info.Channel = 2;
Module_Info.SampleFormat = 1;           //对应ffmpeg的值
Module_Info.SampleRate = frequency;
m_bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfig, audioEncording) * 2;
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channelConfig, audioEncording, m_bufferSize);
if (audioRecord == null)
{
return -1;
}

Module_Info.BufLen = m_bufferSize;
//如果存在先释放
if (Module_Info.Buf != null)
{
Module_Info.Buf = null;
}
Module_Info.Buf = new byte[m_bufferSize];
Module_Info.ActualLen = 0;

//打开麦克风
audioRecord.startRecording();

//填写到list中
list_Module_Info.put(i + m_streamid_accumulation,Module_Info);
list_AudioRecord.put(i + m_streamid_accumulation,audioRecord);
}
return  1;
}

public void uninit(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,AudioRecord> list_AudioRecord)
{
for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + m_streamid_accumulation);
AudioRecord audioRecord = list_AudioRecord.get(i + m_streamid_accumulation);
if (Module_Info.Buf != null)
{
Module_Info.Buf = null;
}
if (audioRecord != null)
{
//停止输出数据
audioRecord.stop();
//关闭摄像头
audioRecord.release();
audioRecord = null;
}
}
list_Module_Info.clear();
list_Module_Info = null;
list_AudioRecord.clear();
list_AudioRecord = null;
}

public  int CameraRead(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,AudioRecord> list_AudioRecord)
{
int ret = 0;

for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + m_streamid_accumulation);
AudioRecord audioRecord = list_AudioRecord.get(i + m_streamid_accumulation);
//如果需要采集
if(Module_Info.Is_ToNext_Module == 1)
{
ret = audioRecord.read(Module_Info.Buf,0,m_bufferSize);
if (ret <  0)
{
return  -1;
}
//回调这一帧的时间戳
long timenow = new Date().getTime();
Module_Info.ActualLen = ret;
Module_Info.pts = timenow;
Module_Info.dts = timenow;
}
}
return  1;
}

public int CameraWrite(HashMap<Integer,LvsAndroidInfo> list_Module_Info,
HashMap<Integer,AudioRecord> list_AudioRecord)
{
int ret = 0;

for (int i = 0 ; i< m_num_device;i++)
{
LvsAndroidInfo Module_Info = list_Module_Info.get(i + m_streamid_accumulation);
AudioRecord audioRecord = list_AudioRecord.get(i + m_streamid_accumulation);
//如果需要采集
if(Module_Info.Is_ToNext_Module == 1)
{
ret = audioRecord.read(Module_Info.Buf,0,m_bufferSize);
if (ret <  0)
{
return  -1;
}
//回调这一帧的时间戳
long timenow = new Date().getTime();
Module_Info.ActualLen = ret;
Module_Info.pts = timenow;
Module_Info.dts = timenow;
}
}
return  1;
}
}

如有错误请指正:


交流请加QQ群:62054820
QQ:379969650.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: