android视频和音频采集及预览

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhuweigangzwg/article/details/52701788

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.



猜你喜欢

转载自blog.csdn.net/zhuweigangzwg/article/details/52701788