轉(zhuǎn)載請注明出處:http://www.reibang.com/p/cad777db008e
本文出自:m2u的簡書
0x00 說明
該文章為本人個(gè)人學(xué)習(xí)的總結(jié)桅滋,如果遺漏或錯(cuò)誤歡迎在評論區(qū)批評指出or補(bǔ)充儿普。如對您有幫助可以細(xì)看之,如希望直接查看本人的學(xué)習(xí)資料來源式廷,可直接跳到0x05 相關(guān)資料一節(jié)查看舶胀。
0x01 概覽
CameraDevice是連接在安卓設(shè)備上的單個(gè)相機(jī)的抽象表示,CameraDevice
支持在高幀率下對捕獲的圖像進(jìn)行細(xì)粒度控制和后期處理.
<p>在Camera2 API中,一個(gè)相機(jī)設(shè)備可能支持的硬件等級有以下幾種(按每個(gè)等級所支持的功能來排序):
LEVEL_3>FULL>LIMIT>LEGACY
按照Google文檔的說法,一般手機(jī)的相機(jī)可能會支持FULL或LIMIT,當(dāng)一個(gè)設(shè)備支持到LIMIT,此時(shí)盡管Camera2 API具有更整潔和高效的接口,然而其只暴露出和舊的Camera API功能相當(dāng)?shù)腁PI,與使用舊的API無異赊堪。
而支持到FULL等級的設(shè)備,則提供了比舊的Camera API大大改進(jìn)的功能履澳,比如支持30fps全高清連拍嘶窄,支持幀之間的手動(dòng)設(shè)置,支持RAW格式的圖片拍攝距贷,快門零延遲以及視頻速拍等特性柄冲。只有在支持FULL級別的設(shè)備上才能完全發(fā)揮Camera2的特性。然而經(jīng)過實(shí)測中發(fā)現(xiàn)忠蝗,目前市面上大多安卓手機(jī)都只支持到最低級別LEGACY(估計(jì)是為了兼容android L 以下的系統(tǒng)现横?)......也就是說在這樣的手機(jī)上使用Camera API和Camera2 API并沒有太大區(qū)別,甚至Camera API的發(fā)揮可能還要好一些阁最。不過戒祠,盡管如此,還是推薦使用Camera2 API速种,畢竟舊的Camera API已經(jīng)被打上deprecated標(biāo)簽姜盈,指不定在未來哪個(gè)android的版本中Camera API就被移除了。相機(jī)設(shè)備所支持的硬件等級是由硬件廠商決定的配阵,可以通過以下CameraCharacteristics
類獲取機(jī)子上的相機(jī)所支持的硬件等級參數(shù):
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int hardwareLevel=characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
其中manager
為CameraManager
實(shí)例馏颂,關(guān)于CameraManager
在上篇文章Camera2開發(fā)(1) --CameraManager類中有介紹。hardwareLevel==1
為FULL棋傍,hardwareLevel==2
為LEGACY救拉,hardwareLevel==0
為LIMIT,hardwareLevel==3
為LEVEL_3瘫拣。
0x02 內(nèi)部類
StateCallback
該類用于接收相機(jī)的連接狀態(tài)的更新亿絮。這些狀態(tài)包括一系列的通知如相機(jī)啟動(dòng)結(jié)束(此時(shí)允許調(diào)用CameraDevice.createCaptureSession(List, CameraCaptureSession.StateCallback, Handler)
創(chuàng)建一個(gè)捕獲會話),相機(jī)斷開連接或關(guān)閉以及相機(jī)出現(xiàn)異常錯(cuò)誤等麸拄。
在調(diào)用CameraDevice.openCamera(String,CameraDevice.StateCallback,Handler)
方法打開相機(jī)時(shí)必須傳入一個(gè)CameraDevice.StateCallback
實(shí)例,以用于接收相機(jī)狀態(tài)的更新和后續(xù)的處理派昧。
典型的CameraDevice.StateCallback
的聲明和使用如下:
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback()
{
@Override
public void onOpened(@NonNull CameraDevice camera)
{
//當(dāng)相機(jī)打開成功之后會回調(diào)此方法
//一般在此進(jìn)行獲取一個(gè)全局的CameraDevice實(shí)例,開啟相機(jī)預(yù)覽等操作
mCameraDevice = camera;//獲取CameraDevice實(shí)例
createCameraPreviewSession();//創(chuàng)建相機(jī)預(yù)覽會話
}
@Override
public void onDisconnected(@NonNull CameraDevice camera)
{
//相機(jī)設(shè)備失去連接(不能繼續(xù)使用)時(shí)回調(diào)此方法感帅,同時(shí)當(dāng)打開相機(jī)失敗時(shí)也會調(diào)用此方法而不會調(diào)用onOpened()
//可在此關(guān)閉相機(jī)斗锭,清除CameraDevice引用
camera.close();
mCameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice camera, int error)
{
//相機(jī)發(fā)生錯(cuò)誤時(shí)調(diào)用此方法
camera.close();
mCameraDevice = null;
}
@Override
public void onClosed(CameraDevice camera)
{
//相機(jī)完全關(guān)閉時(shí)回調(diào)此方法
super.onClosed(camera);
}
};
其中onError(@NonNull CameraDevice camera, int error)
中的error
參數(shù)代表出錯(cuò)的代碼地淀,可參考Google文檔上的錯(cuò)誤代碼說明失球。
0x03 常量
**int TEMPLATE_MANUAL **
Constant Value: 6 (0x00000006)
用于創(chuàng)建一個(gè)直接控制相機(jī)拍照參數(shù)的CaptureRequest
請求。使用該模板創(chuàng)建的請求,相機(jī)的所有自動(dòng)控制都會被禁用(例如自動(dòng)曝光实苞,自動(dòng)白平衡豺撑,自動(dòng)對焦等),并將后期處理參數(shù)設(shè)置成預(yù)覽質(zhì)量黔牵。手動(dòng)控制的參數(shù)(曝光聪轿,感光度等)將被設(shè)置成合理的默認(rèn)值,用戶需要根據(jù)自己想要的預(yù)期效果來調(diào)整這些參數(shù)猾浦。
兼容性:TEMPLATE_MANUAL
在支持MANUAL_SENSOR
功能的設(shè)備上可用陆错。
int TEMPLATE_PREVIEW
Constant Value: 1 (0x00000001)
用于創(chuàng)建一個(gè)相機(jī)預(yù)覽請求。通常情況下金赦,設(shè)置了該模板的預(yù)覽畫面音瓷,相機(jī)會優(yōu)先保證預(yù)覽的幀率。該模板適用于相機(jī)畫面預(yù)覽夹抗,通常將該模板結(jié)合setRepeatingRequest(CaptureRequest, CameraCaptureSession.CaptureCallback, Handler)
創(chuàng)建一個(gè)預(yù)覽請求绳慎。
兼容性:TEMPLATE_PREVIEW
在所有相機(jī)設(shè)備上均適用。
int TEMPLATE_RECORD
Constant Value: 3 (0x00000003)
用于創(chuàng)建錄制視頻的請求漠烧。使用該模板創(chuàng)建的請求將使用標(biāo)準(zhǔn)幀率杏愤,并且后期處理效果的質(zhì)量將被設(shè)置成錄像級別。
兼容性:TEMPLATE_RECORD
可在所有的相機(jī)設(shè)備上使用.已脓。
int TEMPLATE_STILL_CAPTURE
Constant Value: 2 (0x00000002)
用于創(chuàng)建一個(gè)拍照請求珊楼。使用該模板創(chuàng)建的請求會優(yōu)先保證圖像的質(zhì)量,以獲得最好的拍照效果摆舟。
兼容性:可在所有的相機(jī)設(shè)備上使用亥曹。
int TEMPLATE_VIDEO_SNAPSHOT
Constant Value: 4 (0x00000004)
用于創(chuàng)建錄像時(shí)拍照請求。使用該模板創(chuàng)建的請求可以最大化地保證照片的質(zhì)量同時(shí)不會破壞正在錄制的視頻質(zhì)量恨诱。該模板創(chuàng)建的請求通常與CameraCaptureSession.capture(CaptureRequest request, CameraCaptureSession.CaptureCallback callback, Handler handler)
結(jié)合使用媳瞪,其中這里的request
必須是基于TEMPLATE_RECORD模板創(chuàng)建。
兼容性:硬件支持級別高于LEGACY的所有相機(jī)設(shè)備可用照宝。
int TEMPLATE_ZERO_SHUTTER_LAG
Constant Value: 5 (0x00000005)
用于創(chuàng)建零延遲拍照請求蛇受。使用該模板創(chuàng)建的請求將最大化地保證圖片質(zhì)量并且不會損失預(yù)覽圖像的幀率。此時(shí)自動(dòng)對焦/自動(dòng)白平衡和自動(dòng)曝光都應(yīng)處于auto
模式厕鹃。
兼容性:該模板僅在支持PRIVATE_PEPROCESSING
或YUV_PEPROCESSING
特性的相機(jī)設(shè)備上適用兢仰。
0x04 常用的方法
close()
盡可能快地關(guān)閉當(dāng)前相機(jī)設(shè)備的連接。
調(diào)用該方法之后剂碴,所有調(diào)用處于激活狀態(tài)的session
和CameraDevice
其方法的操作都將拋出一個(gè)IllegalStateException
異常把将。當(dāng)相機(jī)完全關(guān)閉后,CameraDevice.StateCallback.onClosed(CameraDevice)
方法會被調(diào)用忆矛,此時(shí)相機(jī)就緒以等待下一次被打開察蹲。
createCaptureRequest(int templateType)
創(chuàng)建一個(gè)用于構(gòu)建capture request的CaptureRequest.Builder實(shí)例,并用templateType模板初始化該實(shí)例请垛。
該設(shè)置會為當(dāng)前指定的CameraDevice
適配最佳的選項(xiàng),因此創(chuàng)建的CaptureRequest
不建議重用到其他的CameraDevice
以免出錯(cuò)洽议。
參數(shù)說明:
- templateType:參考0x03 常量一節(jié)宗收。
** createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)**
通過提供給相機(jī)設(shè)備的目標(biāo)輸出surface集合創(chuàng)建一個(gè)新的相機(jī)捕獲會話(CameraCaptureSession)實(shí)例。
當(dāng)前活動(dòng)的capture session
決定了相機(jī)的每一個(gè)capture request
的輸出surface
(每個(gè)capture request
的輸出surface
都是outputs
的一個(gè)子集)亚兄。比如當(dāng)我需要將捕獲數(shù)據(jù)輸出到預(yù)覽surface
混稽,則需要將預(yù)覽surface
添加到outputs
作為createCaptureSession
的參數(shù)。
在實(shí)際使用中可根據(jù)不同的用例和輸出目標(biāo)來構(gòu)建surface
用于接收相機(jī)輸出的圖像數(shù)據(jù),這里只列出拍照功能可能用到的幾個(gè)审胚,有關(guān)錄像的以后再補(bǔ)充:
- 繪制到一個(gè)SurfaceView:
使用SurfaceView
來顯示預(yù)覽畫面時(shí)匈勋,應(yīng)在SurfaceView
的Surface
創(chuàng)建成功后先通過SurfaceHolder
設(shè)置其大小,再獲取Surface
實(shí)例,如果不設(shè)置膳叨,則相機(jī)會自動(dòng)為其設(shè)置一個(gè)小于且最接近1080p的可用預(yù)覽尺寸:
SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surfaceview);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取所有可用的預(yù)覽尺寸
Size[] sizes=map.getOutputSizes(SurfaceHolder.class);
Size mPreviewSize=sizes[bestSizeIndex];
//設(shè)置surface尺寸
mSurfaceHolder.setFixedSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
//獲取預(yù)覽的surface
Surface surface=mSurfaceHolder.getSurface();
- 通過SurfaceTexture來訪問OpenGL texture:
使用TextureView
來顯示預(yù)覽颓影,要確保手機(jī)的硬件加速開啟才能進(jìn)行。
在創(chuàng)建Surface
之前懒鉴,需要先設(shè)置SurfaceTexture
的大小诡挂,如果不設(shè)置,則相機(jī)會自動(dòng)為其設(shè)置一個(gè)小于且最接近1080p的可用預(yù)覽尺寸:
//獲取SurfaceTexture
SurfaceTexture texture = mTextureView.getSurfaceTexture();
//獲取所有可用預(yù)覽尺寸
Size[] sizes=map.getOutputSizes(SurfactTexture.class);
Size mPreviewSize=sizes[bestSizeIndex];
//設(shè)置SurfaceTexture大小
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
//獲取預(yù)覽的surface
Surface surface = new Surface(texture);
- 結(jié)合MediaCodec進(jìn)行錄像:待補(bǔ)充
- 結(jié)合MediaRecorder進(jìn)行錄像:待補(bǔ)充
- 結(jié)合android.renderscript進(jìn)行高效的YUV處理:待補(bǔ)充
- 在程序中訪問RAW格式或未壓縮的YUV或者壓縮的JPEG格式的圖像數(shù)據(jù):
可創(chuàng)建一個(gè)ImageReader
對象临谱,通過ImageReader
的Surface
來接收相機(jī)圖像并保存圖像數(shù)據(jù):
//************************
//**1.創(chuàng)建ImageReader對象**
//************************
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取指定格式的所有支持尺寸
Size[] sizes=map.getOutputSizes(ImageFormat.JPEG);
//計(jì)算期望的最佳尺寸璃俗,至于怎么計(jì)算則看具體需求。如果該ImageReader的大小沒有在程序中設(shè)置,
//則當(dāng)前相機(jī)設(shè)備將自動(dòng)為該ImageReader設(shè)置一個(gè)支持的小于1080p的尺寸悉默。
Size largestSize = Collections.max(Arrays.asList(sizes), new CompareSizesByArea());
//創(chuàng)建ImageReader
ImageReader mImageReader = ImageReader.newInstance(largestSize.getWidth(), largestSize.getHeight(), ImageFormat.JPEG,/*maxImages*/2);
//...其他操作
/**
* 摘自Google Sample:Camera2Basic
* Compares two {@code Size}s based on their areas.
*/
static class CompareSizesByArea implements Comparator<Size>{
@Override
public int compare(Size lhs, Size rhs)
{
//We cast here to ensure the multiplications won't overflow
return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
}
}
//...其他操作
//************************
//**2.設(shè)置ImageReader.OnImageAvailableListener監(jiān)聽**
//************************
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener()
{
@Override
public void onImageAvailable(ImageReader reader)
{
//在這里調(diào)用(reader.acquireNextImage()獲取圖像數(shù)據(jù)
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
}
};
//...其他操作
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
//************************
//**3.隨后可通過ImageReader.getSurface()方法獲取Surface**
//************************
Surface surface=mImageReader.getSurface();
參數(shù)說明:
- outputs
所有可用于捕獲相機(jī)輸出數(shù)據(jù)的surface
集合城豁。 - callback
CameraCaptureSession.StateCallback實(shí)例,調(diào)用CameraDevice.createCaptureSession
后會回調(diào)callback
中相應(yīng)的方法抄课,可在該回調(diào)中處理創(chuàng)建session
成功或失敗之后的進(jìn)一步操作唱星。 - handler
指定處理該操作的handler
getId()
獲取當(dāng)前相機(jī)設(shè)備的id
0x05 相關(guān)資料
有關(guān)CameraDevice
的使用實(shí)例可參考googlesamples/android-Camera2Basic
轉(zhuǎn)載請注明出處:http://www.reibang.com/p/cad777db008e
本文出自:m2u的簡書
20170115 15:45 by m2u