Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用 这里将大致框架介绍了,但很多人对onPreviewFrame()里的处理提出质疑。认为下面的转换是多余的:
final YuvImage image = new YuvImage(mData, ImageFormat.NV21, w, h, null); ByteArrayOutputStream os = new ByteArrayOutputStream(mData.length); if(!image.compressToJpeg(new Rect(0, 0, w, h), 100, os)){ return null; } byte[] tmp = os.toByteArray(); Bitmap bmp = BitmapFactory.decodeByteArray(tmp, 0,tmp.length);
因为这个mData是byte[ ]格式,转换流程是:byte[ ]---YuvImage----ByteArrayOutputStream---byte[ ]-----Bitmap。乍一看这个转换还真是多余了。看看看goolge的api:
public abstract void onPreviewFrame (byte[] data, Camera camera) Added in API level 1 Called as preview frames are displayed. This callback is invoked on the event thread open(int) was called from. If using the YV12 format, refer to the equations in setPreviewFormat(int) for the arrangement of the pixel data in the preview callback buffers. Parameters data the contents of the preview frame in the format defined by ImageFormat, which can be queried with getPreviewFormat(). If setPreviewFormat(int) is never called, the default will be the YCbCr_420_SP (NV21) format. camera the Camera service object.
大致意思是:可以用getPreviewFormat()查询
支持的预览帧格式。如果setPreviewFormat(INT)
从未被调用,默认将使用YCbCr_420_SP的格式(NV21)。
setPreviewFormat里,它又说:
public void setPreviewFormat (int pixel_format) Added in API level 1 Sets the image format for preview pictures. If this is never called, the default format will be NV21, which uses the NV21 encoding format. Use getSupportedPreviewFormats() to get a list of the available preview formats. It is strongly recommended that either NV21 or YV12 is used, since they are supported by all camera devices. For YV12, the image buffer that is received is not necessarily tightly packed, as there may be padding at the end of each row of pixel data, as described in YV12. For camera callback data, it can be assumed that the stride of the Y and UV data is the smallest possible that meets the alignment requirements. That is, if the preview size is width x height, then the following equations describe the buffer index for the beginning of row y for the Y plane and row c for the U and V planes: yStride = (int) ceil(width / 16.0) * 16; uvStride = (int) ceil( (yStride / 2) / 16.0) * 16; ySize = yStride * height; uvSize = uvStride * height / 2; yRowIndex = yStride * y; uRowIndex = ySize + uvSize + uvStride * c; vRowIndex = ySize + uvStride * c; size = ySize + uvSize * 2;
强烈建议使用NV21格式和YV21格式,而默认情况下是NV21格式,也就是YUV420SP的。因此不经过转换,直接用BitmapFactory解析是不能成功的。事实也是如此。直接解析mData将会得到如下的错误:
另外下面也提到NV21是通用的。
getSupportedPreviewFormats()
Added inAPI level 5
Gets the supported preview formats.NV21
is always supported.YV12
is always supported since API level 12.
如果嫌YuvImage进行压缩解析的慢,只能自己写转换函数了,网上常见的有三种:
一:这里只是一个编码框架
参考这里:Android 实时视频采集—Camera预览采集
// 【获取视频预览帧的接口】 mJpegPreviewCallback = new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] data, Camera camera) { //传递进来的data,默认是YUV420SP的 // TODO Auto-generated method stub try { Log.i(TAG, "going into onPreviewFrame"); //mYUV420sp = data; // 获取原生的YUV420SP数据 YUVIMGLEN = data.length; // 拷贝原生yuv420sp数据 mYuvBufferlock.acquire(); System.arraycopy(data, 0, mYUV420SPSendBuffer, 0, data.length); //System.arraycopy(data, 0, mWrtieBuffer, 0, data.length); mYuvBufferlock.release(); // 开启编码线程,如开启PEG编码方式线程 mSendThread1.start(); } catch (Exception e) { Log.v("System.out", e.toString()); }// endtry }// endonPriview };
二、下面是将yuv420sp转成rgb参考这里:android视频采集
private void updateIM() { try { // 解析YUV成RGB格式 decodeYUV420SP(byteArray, yuv420sp, width, height); DataBuffer dataBuffer = new DataBufferByte(byteArray, numBands); WritableRaster wr = Raster.createWritableRaster(sampleModel, dataBuffer, new Point(0, 0)); im = new BufferedImage(cm, wr, false, null); } catch (Exception ex) { ex.printStackTrace(); } } private static void decodeYUV420SP(byte[] rgbBuf, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; if (rgbBuf == null) throw new NullPointerException("buffer 'rgbBuf' is null"); if (rgbBuf.length < frameSize * 3) throw new IllegalArgumentException("buffer 'rgbBuf' size " + rgbBuf.length + " < minimum " + frameSize * 3); if (yuv420sp == null) throw new NullPointerException("buffer 'yuv420sp' is null"); if (yuv420sp.length < frameSize * 3 / 2) throw new IllegalArgumentException("buffer 'yuv420sp' size " + yuv420sp.length + " < minimum " + frameSize * 3 / 2); int i = 0, y = 0; int uvp = 0, u = 0, v = 0; int y1192 = 0, r = 0, g = 0, b = 0; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; rgbBuf[yp * 3] = (byte) (r >> 10); rgbBuf[yp * 3 + 1] = (byte) (g >> 10); rgbBuf[yp * 3 + 2] = (byte) (b >> 10); } } } public static void main(String[] args) { Frame f = new FlushMe(); } }
三、将YUV420SP转成YUV420格式
参考这里:Android如何实现边采集边上传
private byte[] changeYUV420SP2P(byte[]data,int length){ int width = 176; int height = 144; byte[] str = new byte[length]; System.arraycopy(data, 0, str, 0,width*height); int strIndex = width*height; for(int i = width*height+1; i < length ;i+=2) { str[strIndex++] = data[i]; } for(int i = width*height;i<length;i+=2) { str[strIndex++] = data[i]; } return str; }
至于怎么从YUV420SP中直接提取出Y分量进行后续检测,这个还要研究一番。有知道的大神多赐教。
----------------------------------------------------------------------------------------本文系原创,转载请注明作者:yanzi1225627
相关推荐
Android使用MediaCodec将摄像头采集的视频编码为h264 Android平台上,MediaCodec是Android 4.1(Jelly Bean)引入的一个新的多媒体编码解码器框架,它提供了一个统一的接口来访问各种硬件编码器和解码器。...
在Android平台上,开发人员经常需要处理视频采集和编码任务,特别是在构建实时通信或者录制应用时。本篇文章将深入探讨如何利用Android的MediaCodec API来从摄像头采集图像并进行硬件编码,以及如何通过FFmpeg实现...
海康威视摄像头二次开发项目背景涉及到在公司产品中集成海康威视摄像头的SDK,以实现对海康威视摄像头的控制功能,包括但不限于拍照抓图、视频录制、云台控制及视频实时预览。该二次开发工作是在windows-X64操作系统...
"h5获取摄像头数据,并实时预览"这个话题是关于如何利用H5的媒体API来访问用户设备的摄像头,捕获视频流并实现实时预览。这个功能不仅适用于网页,而且在小程序和内嵌于WebView的应用中也非常常见。以下是对这一技术...
在Android平台上,开发...以上内容概括了Android中利用Camera和SurfaceView进行摄像头预览的关键知识点。在实际开发过程中,还需要考虑设备兼容性、性能优化、用户体验等问题,确保应用能在各种Android设备上稳定运行。
在Android平台上,开发一款应用来预览基于UVC(Universal Video Class)协议的摄像头,并实现截图和录屏功能,是一项技术挑战。UVC协议是USB设备类定义的一部分,主要用于视频设备,如网络摄像头,通过USB接口与主机...
总之,Android摄像头RTMP推流是一个涉及多方面技术的综合任务,包括Android硬件访问、音视频编码、实时传输协议和多线程编程。通过FFMPEG库,开发者可以构建出高效且功能丰富的直播应用。不断学习和实践,才能在这个...
在IT行业中,尤其是在移动开发和多媒体处理领域,硬编码(Hardcoding)是一种常见的技术实践,特别是在处理摄像头数据和视频流时。本项目涉及到的核心技术包括使用SurfaceView与Camera交互、实时视频流处理、H264...
在Android平台上,获取手机摄像头的视频数据是一项常见的任务,它涉及到多媒体处理、设备硬件交互以及用户界面设计。本文将深入探讨如何实现一个类似打开相机应用的效果,让开发者能够捕获和处理摄像头的视频流。 ...
在Android平台上,摄像头采集H264数据并进行解码播放是移动开发中常见的应用场景,尤其是在视频通话、直播、录像等应用中。本教程将详细讲解如何实现这一过程。 首先,我们要了解Android摄像头数据采集的基本流程。...
`CamrService`可能就是实现这个功能的类,它包含了开启摄像头、配置预览界面、捕获视频帧并编码为适合网络传输的格式(如H.264)的代码。 然后,**视频实时传播**涉及到数据编码、压缩以及高效传输。为了实现实时性...
使用Android的`SurfaceView`或`TextureView`可以实现实时预览摄像头画面,并将视频流数据发送到Socket。 7. **性能优化**: 实时视频传输对性能要求较高,因此需要考虑内存管理、帧率控制、带宽优化等策略。例如,...
总的来说,"Android 采用MediaCodec实现Camera预览视频编解码"涉及了Android多媒体处理的核心技术,包括MediaCodec的使用、Camera2 API的集成以及视频编码和容器格式的相关知识。通过深入理解这些概念和实践,开发者...
在本文中,我们将深入探讨如何使用OpenCV库在C++中实现摄像头的实时显示和视频录制功能。OpenCV,全称Open Source Computer Vision Library,是一个强大的计算机视觉库,广泛应用于图像处理、机器学习以及视频分析等...
在Android平台上,摄像头视频录制是移动应用开发中的一个重要功能,特别是在社交、教育、娱乐等领域。本文将深入探讨如何在Android中实现摄像头视频录制,并以"MediaCodech264"为例,讲解使用MediaCodec进行H.264...
至于"TestofCamera"这个文件,很可能是项目中的测试代码或示例应用,它可能包含了实现上述功能的具体步骤和逻辑,包括设置摄像头预览、捕获帧、编码、创建Socket连接以及发送数据等。 总的来说,手机采集摄像头视频...
在Android平台上实现预览监控视频是一项常见的任务,尤其在智能家居、安防系统等领域。海康威视作为知名的监控设备供应商,提供了公开的SDK供开发者集成到自己的应用中,以实现通过手机实时查看监控画面、拍照等功能...
Android摄像头源码可以帮助理解内部的工作流程,如预览数据的处理、图片编码和回调机制。你可以研究以下关键组件: 1. `CameraService`:系统服务,负责摄像头设备的管理。 2. `CameraClient`:Camera1的客户端接口...
总结,自封装的Android摄像头采集类是Android应用开发中的重要组件,它简化了原始Camera API的使用,提高了代码的可读性和可维护性。通过`AndroidCamera.java`和`VideoCallBack.java`这两个文件,我们可以实现完整的...