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

yangxi_001發表於2014-01-14

在第二個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、要編寫橫豎屏鏡頭自動調整的程式碼,否則預覽的影象將是左右顛倒的。

該檔案詳細程式碼如下:

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

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

相關文章