android camera采集、H264编码与Rtmp推流

MediaPlus是基于FFmpeg从零开发的android多媒体组件,主要包括:采集,编码,同步,推流,滤镜及直播及短视频比较通用的功能等,后续功能的新增都会有相应文档更新,感谢关注。

需要了解的就是:YUV采样,数据分布及空间大小计算。 YUV采样:

YUV420P YUV排序如下图:

NV12,NV21,YV12,I420都属于YUV420,但是YUV420 又分为YUV420P,YUV420SP,P与SP区别就是,前者YUV420P UV顺序存储,而YUV420SP则是UV交错存储,这是最大的区别,具体的yuv排序就是这样的: I420: YYYYYYYY UU VV ->YUV420P YV12: YYYYYYYY VV UU ->YUV420P NV12: YYYYYYYY UVUV ->YUV420SP NV21: YYYYYYYY VUVU ->YUV420SP

那么H264编码,为什么需要把android 相机采集的NV21数据转换成YUV420P? 刚开始对这些颜色格式也很模糊,后来找到了真理:因为H264编码必须要用 I420, 所以这里必须要处理色彩格式转换。 MediaPlus采集视频数据为NV21格式,以下描述如何获取android camera采集的每一帧数据,并处理色彩格式转换,代码如下:

  • 获取相机采集数据:

 mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        mParams = mCamera.getParameters();
        setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
        mParams.setPreviewSize(SRC_FRAME_WIDTH, SRC_FRAME_HEIGHT);
        mParams.setPreviewFormat(ImageFormat.NV21); //preview format:NV21
mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        m_camera.setDisplayOrientation(90);
        mCamera.setParameters(mParams); // setting camera parameters
        m_camera.addCallbackBuffer(m_nv21);
        m_camera.setPreviewCallbackWithBuffer(this);
        m_camera.startPreview();
​
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        // TODO Auto-generated method stub
                //data这里就是获取到的NV21数据
        
        m_camera.addCallbackBuffer(m_nv21);//这里要添加一次缓冲,否则onPreviewFrame可能不会再被回调
    }

因为NV21数据的所需空间大小(字节)=宽 x 高 x 3 / 2 (y=WxH,u=WxH/4,v=WxH/4);所以我们需要建立一个byte数组,作为采集视频数据的缓冲区. MediaPlus>>app.mobile.nativeapp.com.libmedia.core.streamer.RtmpPushStreamer 类主要采集音视频数据,并交由底层处理;有两个线程分别用于处理音视频,AudioThread 、VideoThread.

  • 首先看下VideoThread

/**
     * 视频采集线程
     */
    class VideoThread extends Thread {
​
        public volatile boolean m_bExit = false;
        byte[] m_nv21Data = new byte[mVideoSizeConfig.srcFrameWidth
                * mVideoSizeConfig.srcFrameHeight * 3 / 2];
        byte[] m_I420Data = new byte[mVideoSizeConfig.srcFrameWidth
                * mVideoSizeConfig.srcFrameHeight * 3 / 2];
        byte[] m_RotateData = new byte[mVideoSizeConfig.srcFrameWidth
                * mVideoSizeConfig.srcFrameHeight * 3 / 2];
        byte[] m_MirrorData = new byte[mVideoSizeConfig.srcFrameWidth
                * mVideoSizeConfig.srcFrameHeight * 3 / 2];
​
        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
​
            VideoCaptureInterface.GetFrameDataReturn ret;
            while (!m_bExit) {
                try {
                    Thread.sleep(1, 10);
                    if (m_bExit) {
                        break;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ret = mVideoCapture.GetFrameData(m_nv21Data,
                        m_nv21Data.length);
                if (ret == VideoCaptureInterface.GetFrameDataReturn.RET_SUCCESS) {
                    frameCount++;
                    LibJniVideoProcess.NV21TOI420(mVideoSizeConfig.srcFrameWidth, mVideoSizeConfig.srcFrameHeight, m_nv21Data, m_I420Data);
                    if (curCameraType == VideoCaptureInterface.CameraDeviceType.CAMERA_FACING_FRONT) {
                        LibJniVideoProcess.MirrorI420(mVideoSizeConfig.srcFrameWidth, mVideoSizeConfig.srcFrameHeight, m_I420Data, m_MirrorData);
                        LibJniVideoProcess.RotateI420(mVideoSizeConfig.srcFrameWidth, mVideoSizeConfig.srcFrameHeight, m_MirrorData, m_RotateData, 90);
                    } else if (curCameraType == VideoCaptureInterface.CameraDeviceType.CAMERA_FACING_BACK) {
                        LibJniVideoProcess.RotateI420(mVideoSizeConfig.srcFrameWidth, mVideoSizeConf
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值