1. 程式人生 > >Android實時監控專案第三篇:通過攝像頭實時預覽幀視訊

Android實時監控專案第三篇:通過攝像頭實時預覽幀視訊

在第二個Activity中,我們要顯示攝像頭預覽的視訊,佈局檔案很簡單,就一個SurfaceView元件,設定為佔滿整個父元件(這裡不再給出),用來顯示預覽的視訊。

      在對應的Activity檔案中,要獲取SurfaceView的SurfaceHolder,併為其新增一個回撥監聽器,該監聽器傳入一個Callback例項,這裡需要覆寫Callback例項中的三個方法,分別是:

public void surfaceCreated(SurfaceHolder holder)方法,當開啟攝像頭時,該方法被回撥;

public void surfaceChanged(SurfaceHolder holder)方法,當SurfaceView預覽介面的格式或大小發生改變時,該方法被回撥;

public void surfaceDestroyed(SurfaceHolder holder)方法,當SurfaceView被銷燬時,該方法被回撥;

      在surfaceCreated方法中通過私有方法initCreama()對攝像頭各項引數進行初始化,主要是設定預覽視訊的尺寸,每秒顯示的幀數等,設定完引數後,通過setParameters(Camera.Parameters parameters)方法顯示取景畫面,即預覽視訊。在開始預覽前,呼叫setPreviewCallback(PreviewCallback cb)方法來獲取採集到的預覽視訊流資料,從而可以對其進行處理,這一點將在下篇中詳細講解。在開始預覽之後,還要設定自動對焦,不然攝像頭採集到的影象不清晰。

另外,這裡有兩點需要注意:

1、每臺手機的攝像頭所支援的影象預覽或拍攝尺寸不盡相同,如果設定的影象尺寸,攝像頭不支援,則會出錯,因此在真機上測試前,先要確定攝像頭支援哪些尺寸,具體的方法很簡單,這裡不再給出,需要了解的可以參考這篇文章:http://blog.csdn.net/yanzi1225627/article/details/7738736;

2、要編寫橫豎屏鏡頭自動調整的程式碼,否則預覽的影象將是左右顛倒的。

該檔案詳細程式碼如下:

  1. package zyb.org.camera;  
  2. import java.io.IOException;  
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.content.res.Configuration;  
  6. import android.hardware.Camera;  
  7. import android.os.Bundle;  
  8. import android.util.DisplayMetrics;  
  9. import android.view.SurfaceHolder;  
  10. import android.view.SurfaceHolder.Callback;  
  11. import android.view.SurfaceView;  
  12. publicclass CameraActivity extends Activity {  
  13.     private SurfaceView sView = null;  
  14.     private String ipName = null;  
  15.     private SurfaceHolder sHolder = null;  
  16.     privateint screenWidth;  
  17.     privateint screenHeight;  
  18.     private Camera camera = null;  
  19.     privateboolean isPreview = false;   
  20.     public Camera getCamera() {  
  21.         return camera;  
  22.     }  
  23.     @Override
  24.     protectedvoid onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.activity_camera);  
  27.         //從上個Activity中獲取傳遞過來的資料
  28.         Intent intent = getIntent();  
  29.         ipName = intent.getStringExtra("ipname");  
  30.         //獲取螢幕的寬和高
  31.         DisplayMetrics dm = new DisplayMetrics();  
  32.         getWindowManager().getDefaultDisplay().getMetrics(dm);  
  33.         screenWidth = dm.widthPixels;  
  34.         screenHeight = dm.heightPixels;  
  35.         sView = (SurfaceView)findViewById(R.id.sView);    
  36.         sHolder = sView.getHolder();  
  37.         sHolder.addCallback(new Callback() {  
  38.             //釋放camera時,回撥該方法
  39.             @Override
  40.             publicvoid surfaceDestroyed(SurfaceHolder holder) {  
  41.                 if(camera != null){  
  42.                     camera.setPreviewCallback(null);  
  43.                     if(isPreview)  
  44.                         camera.stopPreview();  
  45.                     camera.release();  
  46.                     camera = null;  
  47.                 }  
  48.             }  
  49.             //開啟攝像頭時,回撥該方法
  50.             @Override
  51.             publicvoid surfaceCreated(SurfaceHolder holder) {  
  52.                 initCamera();  
  53.             }  
  54.             @Override
  55.             publicvoid surfaceChanged(SurfaceHolder holder, int format, int width,  
  56.                     int height) {  
  57.                 // TODO Auto-generated method stub
  58.             }  
  59.         });  
  60.     }     
  61.     /** 
  62.      * 初始化攝像頭各引數 
  63.      * */
  64.     privatevoid initCamera(){  
  65.         if(!isPreview)  
  66.             camera = Camera.open();  
  67.         if(camera!=null && !isPreview){  
  68.             try {  
  69.                 Camera.Parameters parameters = camera.getParameters();  
  70.                 //每臺手機的攝像頭所支援的影象預覽或拍攝尺寸不盡相同,
  71.                 //如果設定的影象尺寸,攝像頭不支援,則會出錯,
  72.                 //因此在真機上測試前,先要確定攝像頭支援哪些尺寸
  73.                 parameters.setPreviewSize(screenWidth, screenHeight);  //設定預覽影象的尺寸大小
  74.                 parameters.setPreviewFpsRange(1020);                 //設定每秒顯示10-20幀
  75.                 // 橫豎屏鏡頭自動調整
  76.                 if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE){  
  77.                       parameters.set("orientation""portrait");   
  78.                       parameters.set("rotation"90); // 鏡頭角度轉90度(預設攝像頭是橫拍) 
  79.                       camera.setDisplayOrientation(90); // 在2.2以上可以使用
  80.                  } else{  
  81.                   // 如果是橫屏
  82.                       parameters.set("orientation""landscape");   
  83.                       camera.setDisplayOrientation(0); // 在2.2以上可以使用
  84.                  }   
  85.                 camera.setPreviewDisplay(sHolder);                     //通過SurfaceView顯示取景畫面
  86.                 //回撥處理預覽視訊流類中的onPreviewFrame方法
  87.                 //在onPreviewFrame方法中,啟動傳送視訊流的執行緒
  88.                 camera.setPreviewCallback(new ViedoStream(ipName,CameraActivity.this));      
  89.                 camera.startPreview();           //開始預覽
  90.                 camera.autoFocus(null);         //自動對焦
  91.             } catch (IOException e) {  
  92.                 e.printStackTrace();  
  93.             }  
  94.             isPreview = true;  
  95.         }  
  96.     }  
  97. }  

下篇將講述後臺執行緒傳送預覽幀視訊的操作