分享

一哥技术馆 关于android视频采集的问题,急求解

 arm_embed 2012-12-05
最近在有个项目是关于android的视频采集,要求是捕捉某个事件发生前后30秒的视频片段。以前从没有做过android或多媒体开发,很多概念和技术不是很清楚,在网上各论坛转了很久,大致有个思路(MediaRecorder类不知道能不能满足上面的要求),就是利用Camera的PreviewCallback接口,通过实现onPreviewFrame(byte[] data, Camera camera)来捕捉每一帧数据,然后将data保存到文件里,问题是直接保存的数据无法播放,网上有人提供过decodeYUV420SP方法来将默认的YUV格式转码为RGB格式,问题是无论转码前还是转码后我都不知道应该保存为什么文件,是不是直接保存为后缀名为".3gp"或".mp4"就可以了?
我一直是在模拟器上调试的,不知道是不是一定需要在真机上运行才行。
跪求各达人显显灵,谢啦!

以下是我的代码,请各位达人斧正

Java code
import java.io.File; import java.io.RandomAccessFile; import android.app.Activity; import android.graphics.PixelFormat; import android.hardware.Camera; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.Window; import android.view.WindowManager; public class AndroidCamera extends Activity implements SurfaceHolder.Callback { private SurfaceView mSurfaceView = null; private SurfaceHolder mSurfaceHolder = null; private Camera mCamera = null; private boolean mPreviewRunning = false; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFormat(PixelFormat.TRANSLUCENT); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera); mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.addCallback(this); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(mPreviewRunning) { mCamera.stopPreview(); } Camera.Parameters p = mCamera.getParameters(); p.setPreviewSize(width, height); mCamera.setPreviewCallback(new VideoData(width, height)); mCamera.setParameters(p); try { mCamera.setPreviewDisplay(holder); } catch(Exception e) { e.printStackTrace(); } mCamera.startPreview(); mPreviewRunning = true; } @Override public void surfaceCreated(SurfaceHolder holder) { mCamera = Camera.open(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.v("AndroidCamera", "surfaceDestroyed"); if(mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mPreviewRunning =false; mCamera.release(); mCamera = null; } } } class VideoData implements Camera.PreviewCallback { RandomAccessFile raf=null; byte[] h264Buff =null; public VideoData(int width, int height) { Log.v("androidCamera", "new VideoData"); h264Buff = new byte[width * height *8]; try { Log.v("androidCamera", "Create File: /sdcard/camera.dat start"); File file = new File("/sdcard/camera.3gp"); Log.v("androidCamera", "Create File: /sdcard/camera.dat end"); raf = new RandomAccessFile(file, "rw"); } catch (Exception ex) { ex.printStackTrace(); } } @Override public void onPreviewFrame(byte[] data, Camera camera) { if(data == null) { return; } int previewWidth = camera.getParameters().getPreviewSize().width; int previewHeight = camera.getParameters().getPreviewSize().height; byte[] rgbBuffer = new byte[previewWidth * previewHeight * 3]; decodeYUV420SP(rgbBuffer, data, previewWidth, previewHeight); try { raf.write(rgbBuffer, 0, data.length); } catch(Exception ex) { ex.printStackTrace(); } } protected void finalize() { if (null != raf) { try { raf.close(); } catch (Exception ex) { ex.printStackTrace(); } } try { super.finalize(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } } private 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); } } } }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多