`
phenom
  • 浏览: 409367 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

Android camera 预览帧数和视频通话图片缓存

 
阅读更多
setPreviewFrameRate是在api level1就开始使用了,然后不是简单地设置这个方法就可以让摄像头每秒捕获多少帧数的。
比如我设置2,它一秒不会只捕获2帧数据的,从日志记录来看,相当糟糕,不会是预期的2帧,于是我查找文档,发现这个方法已经废除了。

在api level9时加入了一个方法setPreviewFpsRange (int min, int max)
预览帧数从min到max,这个值再*1000.
这个方法已经在高版本的sdk中取代了旧的setPreviewFrameRate。

如何知道摄像头的预览范围呢?我原以为从1到n,其实不然。
getSupportedPreviewFpsRange()这个方法就可以显示出你的手机摄像头支持的范围。
List<int[]> range=parameters.getSupportedPreviewFpsRange();
        Log.d(TAG, "range:"+range.size());
        for(int j=0;j<range.size();j++) {
        	int[] r=range.get(j);
        	for(int k=0;k<r.length;k++) {
        		Log.d(TAG, TAG+r[k]);
        	}
        }

如i9000会是7-30而不是1-30.。。
所以在Camera.PreviewCallback回调中,onPreviewFrame会得到的帧数就不会小于7了。

我还一直以为预览帧数是2,看到的画面还是很流畅。。。

文档里还有这么一段话:
Gets the supported preview fps (frame-per-second) ranges. Each range contains a minimum fps and maximum fps. If minimum fps equals to maximum fps, the camera outputs frames in fixed frame rate. If not, the camera outputs frames in auto frame rate. The actual frame rate fluctuates between the minimum and the maximum. The values are multiplied by 1000 and represented in integers. For example, if frame rate is 26.623 frames per second, the value is 26623.

如果最大值与最小值是一样的,就是以这个值输出预览,如果不同,则会以这个区间自动输出。
看上去,预览帧数还是不可控制的啊

这样只能自己控制帧数了。比如视频通话的就可以这样处理:

    private BlockingQueue<Object> mFrameList = new ArrayBlockingQueue<Object>(18);存放的帧最多18,多少根据自己的机器状况和网络状态调整,至少我觉得如果缓存太多,内存紧张,而且如果网络不好,一样发不出去,缓存太少,网络状况好的时候就会出现空帧,图像一样不流畅。
当然最好是还是c的编码速度够快,其它都是扯淡。

private void putVideoFrame(byte[] data,int width,int height){
        if(!showVideo){
            Log.d(TAG, "putVideoFrame.已经没有显示视频了。");
            return;
        }
        Log.d(TAG, "putVideoFrame.");
        ///synchronized(mFrameList){
            Object[] obj=new Object[]{data,width,height};
            mFrameList.offer(obj);
        //}
//这个过程本身就是同步的,把预览的帧放入缓存中等待发送。
    }
private PreviewCallback previewCallback=new PreviewCallback() {

        @Override
        public void onPreviewFrame(byte[] _data, Camera _camera) {
            Camera.Parameters parameters=_camera.getParameters();
            final Camera.Size size=parameters.getPreviewSize();
         
                final byte[] copyData = new byte[_data.length];
                System.arraycopy(_data, 0, copyData, 0, _data.length);

                putVideoFrame(copyData, size.width, size.height);
        }
    };
然后建一个线程:
Runnable frameRunnable = new Runnable() {

        @Override
        public void run() {
            while (showVideo&&mStarted) {
                sendVideoFrame();//在这里把帧发出去
                
                if(mFrameList.size()>=mFps){
                	fcount++;
                    Log.d(TAG, "缓存帧又满了。");

                    Object[] obj=(Object[]) mFrameList.poll();
                    mFrameList.clear();
                    mFrameList.offer(obj);
                }
            }
            
            Log.d(TAG, "结束发送线程.");
            //mFrameList.clear();
        }
    };
//满的时候需要将原来的清空,个人觉得如果缓存满了不清空,新预览的帧就会排在后面,如果一定要按顺序发送的话,还是不能达到流畅的效果。

最后是发送的:
private void sendVideoFrame() {
        //Log.d(TAG, "sendVideoFrame.");
        Object[] obj=null;
            obj=(Object[]) mFrameList.poll();
        Log.d(TAG, "obj:"+obj);
        if (null!=obj) {
            long start=System.currentTimeMillis();
            byte[] data=(byte[]) obj[0];
            Integer width=(Integer) obj[1];
            Integer height=(Integer) obj[2];
            
            if (发送条件) {
                int res=engine.SendVideoFrame(data, width, height);
                long end=System.currentTimeMillis();
                start=end-start;
                //限制发送的帧数。
                end=delta-start;
                Log.d(TAG, "发送一次图像需要时间:"+(start)+" width:"+width+" height:"+height+
                    " count:"+count+++" res:"+res+" fcount:"+fcount+" end:"+end);
                if (end>0) {//为什么在这里睡眠呢,假设现在的网络好,机器强劲,其实也没有必要一直发送视频帧的,这里就可 以限制发送。预计发送一次为200毫秒,一秒为5帧。那发送的时间小于200的就要等待了。这样就限制了,如果多于200毫秒的,就不要睡眠了。个人感觉,如果帧数到达12左右,基本感觉是较流畅了,再往上,不会有太大的区别(前提:目前手机也达到不20+,而且网络。。。)
                    try {
                        Thread.sleep(end);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                Log.d(TAG, "无法发送视频:"+engine);
            }
            obj = null;
        } else {
            try {
                Thread.sleep(20l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

最后,建一个线程发送:Thread mFrameThread=null;
mFrameThread=new Thread(frameRunnable);
                //mFrameThread.setPriority(4);
                mFrameThread.start();
在打开预览时就可以启动这个线程来发送图片了,在关闭预览时,结束发送线程。
在doubango中的ngn栈,它是使用c来处理这些东西的,对于 java,只需要调用jni方法直接把视频帧传入即可,没有这么多的缓存处理(有可能是在c端处理的,没有缓存是不行地)。

分享到:
评论
2 楼 phenom 2012-11-19  
完整的代码不能给,这个主要说明,在预览后,将帧保存起来,在一个列表中,然后另启动一个线程来发送帧(包含压缩,编码,发送,这部分由c处理。)。
如果在onPreviewFrame里面直接操作这些,这是在ui线程的。
在H264Android中有示例,作用是类似的,就是将预览的帧保存,供x264编码, 这个代码可以给。可以在h264编译这篇文章找到x264编码的代码,但里面的AndroidVideo.java在这里更新
ihopethatwell 写道
楼主,这个事例有完整demo?看着还是不是很明白

1 楼 ihopethatwell 2012-11-19  
楼主,这个事例有完整demo?看着还是不是很明白

相关推荐

    Android 采用MediaCodec实现Camera预览视频编解码

    总的来说,"Android 采用MediaCodec实现Camera预览视频编解码"涉及了Android多媒体处理的核心技术,包括MediaCodec的使用、Camera2 API的集成以及视频编码和容器格式的相关知识。通过深入理解这些概念和实践,开发者...

    从camera的onPreviewFrame捕捉到预览帧保存成视频,然后合并成视频

    从camera的onPreviewFrame捕捉到预览帧保存成视频,然后合并成视频

    Android Camera2 Demo - 实现相机预览、拍照、录制视频功能

    其中包括一个自己写的Camera2的Demo,支持预览、拍照和视频录制,以及若干个网上找的,具有参考价值的Camera2 Demo。 具体看我的博客 : https://blog.csdn.net/EthanCo/article/details/131371887 ...

    Android camera2预览和取数据

    1. 使用`ImageReader`:创建一个`ImageReader`实例,设置需要的图像格式(如JPEG或YUV)、最大缓存帧数等。 2. 设置回调:通过`ImageReader.setOnImageAvailableListener()`注册监听器,当有新帧可用时,该监听器会...

    Android原生Camera2完成预览和拍照

    3. 创建CaptureSession:使用`CameraDevice.createCaptureSession()`创建一个CaptureSession,指定预览Surface和其他可能的目标,如图片或视频录制的输出流。 4. 设置预览配置:构建一个CaptureRequest,设置预览的...

    Android CameraX Demo : 实现预览/拍照/录制视频/图片分析/对焦/切换摄像头等操作

    我自己写的Android CameraX Demo,实现了预览/拍照/录制视频/图片分析/对焦/切换摄像头等操作。 具体详见我的博客 : https://blog.csdn.net/EthanCo/article/details/125603671

    android camera2实现实时预览和拍照

    本文将深入探讨如何使用`Android Studio`和`Camera2` API来实现实时预览以及拍照功能,并将照片以`.fpg`格式保存到手机中。 首先,我们需要在`build.gradle`文件中添加必要的依赖项,确保项目可以使用`Camera2` API...

    Android Camera1 Demo - 实现预览、拍照、录制视频功能

    由于工作中需要用到Camera1,所以花了两天时间研究了以下,使用Android Camera1 API实现了相机预览、拍照和录制视频的功能。 资源中有个MyCamera1Demo.apk可以直接安装运行,MyCamera1Demo.zip是Demo源码。 具体详见...

    android camera mirror 使用SurfaceView自定义相机视频实现预览时左右镜像,实现镜子效果

    android camera mirror 前置后置相机视频预览时左右镜像,实现镜子效果 基于以下网址实现的android studio项目源代码包,可以直接打开使用 https://blog.csdn.net/mbrose/article/details/80167781 代码做了一...

    Android camera实时预览 实时处理,人脸识别示例

    在Android平台上,开发一款应用实现相机的实时预览和人脸识别功能是一项常见的需求。本文将深入探讨如何使用Android camera API来实现实时预览,并结合面部识别技术,为用户提供一个简单的面部认证示例。 首先,...

    Android 实例实现自定义Camera和前后置摄像头切换以及图片缩小放大预览

    3.实现Camera拍照后图片缩小显示以及正常预览; 4.实现Camera拍照后图片保存; 在具体实现代码之前,我们先来了解一下Android api对实现自定义Camera的介绍。 根据api的介绍,对于Camera应用可以简单总结以下几个...

    硬编码,使用SurfaceView和Camera取帧并保存本地.h264和上传Socket实时视频

    `Camera`类是Android SDK中的一个关键组件,它允许开发者访问设备的摄像头,捕获和处理图像或视频。在这个项目中,我们不仅打开摄像头,还会对每一帧图像进行处理。这通常涉及到设置摄像头参数,如分辨率、帧率等,...

    Camera2GetPreview:在 Android Camera2 中获取和处理预览帧的示例工程

    总结,"Camera2GetPreview"项目是一个极好的起点,帮助开发者了解如何在Android应用中利用Camera2 API获取和处理相机预览帧。通过学习和分析提供的源码,不仅可以掌握基本的预览功能,还能探索更高级的图像处理技术...

    Android Camera Socket 传视频

    在Android平台上,开发一款能够利用Camera进行视频拍摄,并通过Socket实时传输到服务器的应用是一项技术挑战。这个项目的核心在于实现Camera的高级功能以及网络通信的稳定性。以下是对标题和描述中涉及知识点的详细...

    android 原生人脸识别Camera和Camera2的示例

    本文将详细讲解如何利用Android原生的`Camera`和`Camera2` API来实现这一功能。 首先,我们从`Camera` API开始。`Camera` API是Android早期版本提供的人脸检测接口,通过`FaceDetector`类来实现。以下是一些关键...

    Android Camera添加水印(编码)

    "Android Camera添加水印(编码)"这一主题主要涉及如何在用户拍摄照片或录制视频时,实时地将自定义的水印信息叠加到图像或视频帧上。下面我们将深入探讨这个话题,包括必要的理论知识、实现方法以及可能遇到的问题。...

    camera preview test sample

    总的来说,"camera preview test sample"是一个典型的Android Camera应用示例,它涵盖了Camera预览、预览回调以及SurfaceView的使用,是学习和理解Android Camera API的重要参考资料。开发者可以通过这个项目深入...

    Android中关于自定义相机预览界面拉伸问题

    在Android开发中,自定义相机预览界面的拉伸问题是一个常见的挑战,尤其是在处理不同设备和屏幕方向变化时。本文将深入探讨这个问题,并提供解决方案。 首先,理解问题的根本原因至关重要。当我们在Android应用中...

    android camera 数据预览和处理代码

    Android Camera API允许开发者捕获图像和视频,同时提供了对图像数据预览和处理的能力。本篇将深入探讨如何利用Android Camera API进行数据预览和处理,特别是在面部识别场景中的应用。 首先,我们需要创建一个...

Global site tag (gtag.js) - Google Analytics