ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android不显示Camera视频获取摄像头视频帧数据

2021-11-29 21:04:27  阅读:284  来源: 互联网

标签:视频 isNew int private mCamera public Camera Android final


1、在Activity界面代码中:
private var mCamera: Camera? = null
private val mWidth = GwApplication.DEFAULT_REMOTE_WIDTH_EXT
private val mHeight = GwApplication.DEFAULT_REMOTE_HEIGHT_EXT
private var imgData: ImageData = ImageData(mWidth, mHeight)

/**
 * Camera初始化
 **/
private fun initCameara() {
    //log("====initCameara()")
    try {
        mCamera = Camera.open(GwApplication.DEFAULT_CR_CAMERA)
        val params = mCamera!!.getParameters()
        params.previewFormat = ImageFormat.NV21
        params.setPreviewSize(mWidth, mHeight)
        //params.pictureFormat = ImageFormat.NV21
        params.setPictureSize(mWidth, mHeight)
        //params.zoom = 0
        //params.setRotation(0)
        params.setPreviewFpsRange(10, 15)
        mCamera!!.setParameters(params)
    } catch (ex: RuntimeException) {
        ex.printStackTrace()
    }
}

/**
 * 开始监听回调,设置预览
 **/
private fun setCallback() {
    //log("====setCallback()")
    try {
        // 主要是surfaceTexture获取预览数据,但不显示
        val surfaceTexture = SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES)
        mCamera!!.setPreviewTexture(surfaceTexture)
    } catch (e: IOException) {
        e.printStackTrace()
    }
    // 设置 mCamera.addCallbackBuffer(mPreviewData) 后才会回调,旨在每处理完一帧数据回调一次
    mCamera!!.setPreviewCallbackWithBuffer(mPreviewCallback)
    mCamera!!.addCallbackBuffer(imgData.data)
    mCamera!!.startPreview()
}

/**
 * 帧数据监听实现
**/
private val mPreviewCallback =
    android.hardware.Camera.PreviewCallback { data, camera -> // 在此处处理当前帧数据,并设置下一帧回调
        //log("====PreviewCallback()")
        imgData.setTempData(data)
        mCamera!!.addCallbackBuffer(imgData.data)
        //        if (isShow) {
        //            showPic(imgData.previewData)
        //        }
    }

/**
 * 关闭相机
**/
private fun closeCamera() {
    mCamera!!.stopPreview()
    mCamera!!.setPreviewCallbackWithBuffer(null)
    mCamera!!.release()
    mCamera = null
}

/**
 * 显示图片
 **/
private fun showPic(data: ByteArray) {
    val time = System.currentTimeMillis()
    try {
        val image = YuvImage(data, ImageFormat.NV21, mWidth, mHeight, null)
        if (image != null) {
            val stream = ByteArrayOutputStream()
            image.compressToJpeg(Rect(0, 0, mWidth, mHeight), 80, stream)
            runOnUiThread {
                val curTime = System.currentTimeMillis()
                ivCamera.setImageBitmap(null)
                releaseBitmap()
                mBitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size())//fastYUVtoRGB!!.convertYUVtoRGB(data, mWidth, mHeight)
                stream.close()
                ivCamera.setImageBitmap(mBitmap)
                ivCamera.invalidate()
            }
        }
    } catch (e: Exception) {
    }
}

private fun releaseBitmap() {
    if(mBitmap != null) {
        if(!mBitmap!!.isRecycled) {
            mBitmap!!.recycle()
        }
        mBitmap = null
    }
}

2、屏幕和视频图像的效果图:
在这里插入图片描述

其他依赖代码:
ImageData.java文件

/**

  • author zoufeng

  • date:2021/10/15

  • desc:
    */
    public class ImageData {
    private int width;
    private int height;
    private int size;
    private byte[] data;
    private byte[] temp;
    private Boolean isNew;

    public ImageData(int width, int height) {
    this.width = width;
    this.height = height;
    size = width * height * 3 / 2;
    data = new byte[size];
    temp = new byte[size];
    isNew = true;
    }

    public int getWidth() {
    return width;
    }

    public int getHeight() {
    return height;
    }

    public byte[] getData() {
    return data;
    }

    public void setTempData(byte[] preData) {
    synchronized (isNew) {
    if(!isNew) {
    System.arraycopy(preData, 0, temp, 0, preData.length);
    isNew = true;
    }
    }
    }

    public byte[] getTempData() {
    return temp;
    }

    public boolean isNew() {
    return isNew;
    }

    public void setNew(boolean isNew) {
    synchronized (this.isNew) {
    this.isNew = isNew;
    }
    }
    }

FastYUVtoRGB.java文件:(用于YUV直接转换成Bitmap,速度比较快,图像转换在4毫秒一下。)

/**

  • author zoufeng
  • date:2021/11/17
  • desc:
    */
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.renderscript.Allocation;
    import android.renderscript.Element;
    import android.renderscript.RenderScript;
    import android.renderscript.ScriptIntrinsicYuvToRGB;
    import android.renderscript.Type;

/**

  • 使用RenderScript将视频YUV流转换为BMP

  • 注:这个类适用于CameraPreview不变的情况
    */
    public class FastYUVtoRGB {
    private RenderScript rs;
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
    private Type.Builder yuvType, rgbaType;
    private Allocation in, out;

    public FastYUVtoRGB(Context context) {
    rs = RenderScript.create(context);
    yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
    }

    public Bitmap convertYUVtoRGB(byte[] yuvData, int width, int height) {
    if (yuvType == null) {
    yuvType = new Type.Builder(rs, Element.U8(rs)).setX(yuvData.length);
    in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

         rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
         out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
     }
     in.copyFrom(yuvData);
     yuvToRgbIntrinsic.setInput(in);
     yuvToRgbIntrinsic.forEach(out);
     Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
     out.copyTo(bmpout);
     return bmpout;
    

    }

    /**

    • Returns a transformation matrix from one reference frame into another.

    • Handles cropping (if maintaining aspect ratio is desired) and rotation.

    • @param srcWidth Width of source frame.

    • @param srcHeight Height of source frame.

    • @param dstWidth Width of destination frame.

    • @param dstHeight Height of destination frame.

    • @param applyRotation Amount of rotation to apply from one frame to another.

    •                        Must be a multiple of 90.
      
    • @param flipHorizontal should flip horizontally

    • @param flipVertical should flip vertically

    • @param maintainAspectRatio If true, will ensure that scaling in x and y remains constant,

    •                        cropping the image if necessary.
      
    • @return The transformation fulfilling the desired requirements.
      */
      public static Matrix getTransformationMatrix(
      final int srcWidth,
      final int srcHeight,
      final int dstWidth,
      final int dstHeight,
      final int applyRotation, boolean flipHorizontal, boolean flipVertical,
      final boolean maintainAspectRatio) {
      final Matrix matrix = new Matrix();

      if (applyRotation != 0) {
      if (applyRotation % 90 != 0) {
      throw new IllegalArgumentException(String.format(“Rotation of %d % 90 != 0”, applyRotation));
      }

       // Translate so center of image is at origin.
       matrix.postTranslate(-srcWidth / 2.0f, -srcHeight / 2.0f);
      
       // Rotate around origin.
       matrix.postRotate(applyRotation);
      

      }

      // Account for the already applied rotation, if any, and then determine how
      // much scaling is needed for each axis.
      final boolean transpose = (Math.abs(applyRotation) + 90) % 180 == 0;

      final int inWidth = transpose ? srcHeight : srcWidth;
      final int inHeight = transpose ? srcWidth : srcHeight;

      int flipHorizontalFactor = flipHorizontal ? -1 : 1;
      int flipVerticalFactor = flipVertical ? -1 : 1;

      // Apply scaling if necessary.
      if (inWidth != dstWidth || inHeight != dstHeight) {
      final float scaleFactorX = flipHorizontalFactor * dstWidth / (float) inWidth;
      final float scaleFactorY = flipVerticalFactor * dstHeight / (float) inHeight;

       if (maintainAspectRatio) {
           // Scale by minimum factor so that dst is filled completely while
           // maintaining the aspect ratio. Some image may fall off the edge.
           final float scaleFactor = Math.max(Math.abs(scaleFactorX), Math.abs(scaleFactorY));
           matrix.postScale(scaleFactor, scaleFactor);
       } else {
           // Scale exactly to fill dst from src.
           matrix.postScale(scaleFactorX, scaleFactorY);
       }
      

      }

      if (applyRotation != 0) {
      // Translate back from origin centered reference to destination frame.
      float dx = dstWidth / 2.0f;
      float dy = dstHeight / 2.0f;
      matrix.postTranslate(dx, dy);
      // postScale中心点如果出错,图像不会被变换
      matrix.postScale(flipHorizontalFactor, flipVerticalFactor, dx, dy);
      }

      return matrix;
      }

    /*
    /*
    example
    final Canvas canvas = new Canvas(out);
    // 这里的空白bitmap尺寸需要与变换后的预期尺寸一致
    Bitmap src = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888);
    Matrix transformation = getTransformationMatrix(src.getWidth(), src.getHeight(), targetWidth, targetHeight, rotation,true,false, true);
    canvas.drawBitmap(src, transformation, null);
    */
    }

标签:视频,isNew,int,private,mCamera,public,Camera,Android,final
来源: https://blog.csdn.net/bluefire1126/article/details/121619122

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有