学习Android camera笔记 & 调用流程

摘要:
那就是Runnable接口,然后把Runnable的子类对象传递给Thread类再创建Thread对象.总之都是需要创建Thread对象,然后调用Thread类的start方法启动线程。

参考:http://blog.csdn.net/xingyu19871124/article/details/7750189
http://blog.csdn.net/BonderWu/article/details/5814278
http://blog.chinaunix.net/uid-2630593-id-3307176.html
http://zhidao.baidu.com/question/388864295.html

注:把本文内容复制到source insight中查看效果较好
线程与进程:子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文。
Handler与线程: 其实Handler并不是开辟新线程的概念,Android主要的考虑到更新界面的问题,一般情况下,更新界面(Activity)都是在主线程中更新的,
这样就遇到了一个问题,比方说:在下载文件时候我们需要进度条显示下载进度,界面需要更新(数据是不断变的,也就是下载的大小是不断变的,要是直接
在主线程中更新,就会造成程序的堵塞,程序很容易崩溃,通常这样联网耗时的工作需要开辟另外一个线程的,这样就不会影响主程序了),好了,到这里联
网操作一般都需要开辟新线程了吧。
接下来就来说Handler了,刚刚我说了Handler不是开辟新线程,在我看来,Handler更像是主线程的秘书,是一个触发器,负责管理从子线程中得到更新的数据,
然后在主线程中更新界面。简单说下进度条的那个: 下载了多少的数据都是在子线程中得到的,在子线程中通过Handler的sendMessage()方法发送得到的下载
的数据,当你调用了sendMessage方法后,Handler就会回调(也就是自动调用)Handler中的 HandlerMessage方法。
启动线程:Android启动线程和JAVA一样有两种方式,一种是直接Thread类的start方法,也就是一般写一个自己的类来继承Thread 类。
另外一种方式其实和这个差不多啊! 那就是Runnable接口,然后把Runnable的子类对象传递给Thread类再创建Thread对象.总之都是需要创建Thread对象,
然后调用Thread类的start方法启动线程。区别就是,一个是直接创建Thread对象,另外一个是需要implement了Runnable接口对象作为创建Thread对象的参数.
Runnable其实我们称为线程任务。
第一种方式一般是这样用:
Class MyThread extends Thread{
public void run(){
//你要实现的代码
}
}
在主线程中启动这个线程:
public class Test{
public static void main(String[] args){
new MyThread().start();//启动了我们的线程了
}
}
2,第二种方式一般是这样用:
public class MyRunnable implements Runnable{
public void run(){
//你需要实现的代码
}
}
在主线程中启动这个线程:
public class Test{
public static void main(String[] args){
Thread t=new Thread(new MyRunnable());//这里比第一种创建线程对象多了个任务对象
t.start();
}
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cpp:
LOGD("dyyr - log %s, %s", __FILE__, __FUNCTION__);
打开camera/唤醒camera 大致流程途径源文件:
Camera.java onCreate() log1
开启一个新线程,在此线程中open camera
mCameraOpenThread的run()
log2
运行构造函数中的run()
是上述两种开启线程方法中的第一种
Then do something about rotation and else.
在onCreate()中以mCameraOpenThread.join();这句等待该线程完成它的任务
再开启预览线程mCameraPreviewThread.start();
mCameraPreviewThread的run()
1872 log14
startPreview()
log14.5
mCameraDevice是在log4的位置定义的,是log5返回的一个android.hardware.Camera对象
(因为log5源文件第一句:package android.hardware;)
这个对象的startPreview方法声明在log5下面。481行
而它在log15定义。
Util.java openCamera() log3
CameraHolder.java open() log4
Applications
---------------------------------------------------------------------------------------------------------------------------
Camera.java open() log5
Framework
---------------------------------------------------------------------------------------------------------------------------
android_hardware_camera.cpp
android_hardware_Camera_native_setup()
log6
android_hardware_Camera_startPreview()
log15
Camera.cpp connect() log7
startPreview() log16
CameraService.cpp connect() log8 IServiceManager.cpp ServiceManager.java(comfirmed)
log8.1
log8.2
Client() log8.3~8.8
怎么到下面的log9?
startPreview() log17
startCameraMode() log18
startPreviewMode()log19
JNI
---------------------------------------------------------------------------------------------------------------------------
进入camera之前(开机时),camera初始化
CameraHardwareDevice.cpp Initialize() log'1
ALCameraFactory.cpp device_open() log9 (name=0) V4L2CameraDevice.cpp Initialize() log'2
cameraDeviceOpen() log10
CameraHardware.cpp connectCamera() log11 V4L2Camera.cpp Initialize() log'3
startPreview() log20
doStartPreview() log21
V4L2CameraDevice.cpp connectDevice() log12 V4L2Camera.h WorkerThread() log'4 上述两种开启线程方法中的第一种,但并没有run(),
所以还没有真正开启线程,初始化了一个指针V4L2Camera* camera_dev
openCameraDev() log13
在这个最终打开设备文件的函数中,open()得到文件描述符后,
用iotrl()函数做了一些配置然后返回了
PreviewWindow.cpp startPreview() log22
onNextFrameAvailableHW() log23
通过perform向mPreviewWindow窗体发送消息
打开camera并开启预览的流程跟到这里。
camera.cfg
HAL
---------------------------------------------------------------------------------------------------------------------------
gc0308.c
Sys_config1.fex
Kernel
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cpp:
LOGD("dyyr - log %s, %s", __FILE__, __FUNCTION__);
Camera.java
1117 public void onCreate(Bundle icicle) { //打开
......
mCameraOpenThread.start(); // 1097
......
}
1097 Thread mCameraOpenThread = new Thread(new Runnable() {
public void run() {
try {
mCameraDevice = Util.openCamera(Camera.this, mCameraId); //Util.java 267
}
.......
}
}
1532 protected void doOnResume() { //唤醒
......
Util.openCamera(this, mCameraId); //Util.java 267
......
}
1836 private void startPreview() {
......
if (mCameraPreviewThread != null) {
synchronized (mCameraPreviewThread) {
mCameraPreviewThread.notify(); //开启预览线程
}
}
......
}
Util.java package/apps/.../camera
267 CameraHolder.instance().open(cameraId);
CameraHolder.java package/apps/.../camera
131 android.hardware.Camera.open(cameraId); //无法自动定位,frameworks/base/core/java/android/hardware/Camera.java 264 open()
packages/apps/camera/src/com/android/camera/ --------> Camera.apk
Applications
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Camera.java frameworks/base/core/java/android/hardware/Camera.java --------> framework.jar
264 public static Camera open(int cameraId) {
return new Camera(cameraId);
} //open函数是一个静态方法,构造一个Camera对象
285 Camera(int cameraId) { //构造函数
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
native_setup(new WeakReference<Camera>(this), cameraId); //310
}
310 private native final void native_setup(Object camera_this, int cameraId); 其对应于android_hardware_Camera.cpp的android_hardware_Camera_native_setup方法,为什么????
貌似是有函数会去按照camMethods数组匹配
Frameworks
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
android_hardware_camera.cpp frameworks/base/core/jni
458 // connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp<Camera> camera = Camera::connect(cameraId); //无法自动定位. Camera.cpp 128
//Camera C/S架构的客户端调用connect函数向服务器发送连接请求,
//这个Camera类的声明在Camera.h (android4.0\frameworks\base\include\camera)
if (camera == NULL) {
jniThrowRuntimeException(env, "Fail to connect to camera service");
return;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
jniThrowRuntimeException(env, "Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
return;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz
, camera);
context->incStrong(thiz);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context, (int)context.get());
}
Camera.cpp frameworks/base/libs/camera
128 sp<Camera> Camera::connect(int cameraId)
{
LOGV("connect");
sp<Camera> c = new Camera();
const sp<ICameraService>& cs = getCameraService(); //获取一个Camera服务实例,本源文件40行
if (cs != 0) {
c->mCamera = cs->connect(c, cameraId); //然后执行服务端的connect()函数,并返回一个ICamera对象赋值给Camera 的mCamera,
//CameraService.cpp 185~254
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
40 // establish binder interface to camera service
const sp<ICameraService>& Camera::getCameraService()
{
Mutex::Autolock _l(mLock);
if (mCameraService.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager(); //无法自动定位,调用的是IServiceManager.cpp(frameworks/base/libs/binder) 34
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.camera")); //无法自动定位,搜索符号getService,定位到ServiceManager.java 49
if (binder != 0)
break;
LOGW("CameraService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
if (mDeathNotifier == NULL) {
mDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(mDeathNotifier);
mCameraService = interface_cast<ICameraService>(binder); //mCameraService是一个ICamerService类型,
//更加具体具体一点来讲应该是BpCameraService,因为在这个类中实现了ICameraService的方法。
}
LOGE_IF(mCameraService==0, "no CameraService!?");
return mCameraService;
}
IServiceManager.cpp frameworks/base/libs/binder
34 sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>( //得到上面要的sm,它的类型是"sp<IServiceManager>",
//sp<T>是android的智能指针,它持有一个T类实例,并负责在必要时释放此实例
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
我们有必要关注一下interface_cast,通过代码跟踪:看到它的实现
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
通过模板替换就是:
inline sp< IServiceManager > interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
看来asInterface是IServiceManager的一个成员函数,我们打开IServiceManager.cpp/
h文件,我们并没有发现该函数,那它到底在哪儿呢,仔细观察IServiceManager.cpp
,发现里面有个IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
在IServiceManager.h里面发现了DECLARE_META_INTERFACE(ServiceManager);
通过跟踪这两个宏发现DECLARE_META_INTERFACE声明了一个变量和两个函数...
interface_cast<IServiceManager>实际上返回了一个BpServiceManager,在创建一个BpServiceManager时,有些细节还是需要注意:...
ServiceManager.java frameworks/base/core/java/android/os
49 public static IBinder getService(String name) {
Log.d(TAG, "dyyr - getService");
try {
IBinder service = sCache.get(name); //sCache是个Hashmap<String,IBinder>,用参数name:"media.camera"get这个IBinder,
//那么,这个media.camera是源代码里配置好的还是开机后添加进去的?何时添加的?
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
CameraService.cpp frameworks/base/services/camera/libcameraservice
185 sp<ICamera> CameraService::connect( //服务端connect()
const sp<ICameraClient>& cameraClient, int cameraId) {
LOGE("dyyr - CameraService.cpp connect");
int callingPid = getCallingPid();
sp<CameraHardwareInterface> hardware = NULL; //先实例化Camera Hal接口 hardware,
......
246 if (hardware->initialize(&mModule->common) != OK) { //hardware调用initialize()进入HAL层打开Camear驱动, CameraHardwareDevice.cpp 52
hardware.clear();
return NULL;
}
client = new Client(this, cameraClient, hardware, cameraId, info.facing,
callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client; //返回的其实是它内部类client的一个实例。
}
//Camera系统使用的是Server-Client机制,Service和Client位于不同的进程中,进程间使用Binder机制进行通信,
//Service端实际实现相机相关的操作,Client端通过Binder接口调用Service对应的操作。
//如下图所示
android_hardware_camera.cpp fremework/base/core/jni --------> libandroid_runtime.so
|
|
------ | --------------------------
| --------- --------- |
| | Client | | Service |-----------Binder IPC---------
| --------- --------- | |
| libui.so | |
----------------------------------- |
------
|
Camera服务 |
CameraService.cpp等 frameworks/base/camera/libcameraservice/ --------> libcameraservice.so <------------------------------------
( UI 库 frameworks/base/libs/ui/camera --------> libcamera_client.so )
JNI
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CameraHardwareDevice.cpp device/softwinner/common/hardware/camera/
52 status_t CameraHardwareDevice::Initialize()
{
F_LOG;
// instance V4L2CameraDevice object
mV4L2CameraDevice = new V4L2CameraDevice(this, mCameraID);
if (mV4L2CameraDevice == NULL)
{
LOGE("Failed to create V4L2Camera instance");
return NO_MEMORY;
}
status_t res = mV4L2CameraDevice->Initialize(); //V4L2CameraDevice.cpp 71
......
}
V4L2CameraDevice.cpp device/softwinner/common/hardware/camera/
71 status_t V4L2CameraDevice::Initialize()
{
F_LOG;
return V4L2Camera::Initialize(); //V4L2Camera.cpp 66
}
V4L2Camera.cpp device/softwinner/common/hardware/camera/
66 status_t V4L2Camera::Initialize()
{
LOGE("dyyr - %s, %s", __FILE__, __FUNCTION__);
F_LOG;
if (isInitialized()) {
LOGW("%s: V4L2Camera device is already initialized: mState = %d",
__FUNCTION__, mState);
return NO_ERROR;
}
/* Instantiate worker thread object. */
mWorkerThread = new WorkerThread(this); //V4L2Camera.h 325
if (getWorkerThread() == NULL) {
LOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
return ENOMEM;
}
mState = ECDS_INITIALIZED;
return NO_ERROR;
}
V4L2Camera.h device/softwinner/common/hardware/camera/
325 inline explicit WorkerThread(V4L2Camera* camera_dev)
: Thread(true), // Callbacks may involve Java calls. //顶层打开/唤醒Camera的流程跟到这里---------------------------未完待续
mCameraDevice(camera_dev),
mThreadControl(-1),
mControlFD(-1)
{
}
------------------------------------------------------------------
下面是camera的HAL层open底层驱动的方法,没有使用传统的这一句:module->methods->open(module, mName.string(),(hw_device_t **)&mDevice),而走的是V4L2途径:
HALCameraFactory.cpp device/softwinner/common/hardware/camera/
201 struct hw_module_methods_t HALCameraFactory::mCameraModuleMethods = {
open: HALCameraFactory::device_open // 160
};
160 int HALCameraFactory::device_open(const hw_module_t* module,
const char* name,
hw_device_t** device)
{
F_LOG;
/*
* Simply verify the parameters, and dispatch the call inside the //只需确定参数,并调用HALCamera 实例.
* HALCameraFactory instance.
*/
......
return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device); // 118
}
118 int HALCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
{
LOGV("%s: id = %d", __FUNCTION__, camera_id);
......
return mHardwareCameras[camera_id]->connectCamera(device); //CameraHardware.cpp 435
}
CameraHardware.cpp device/softwinner/common/hardware/camera/
435 status_t CameraHardware::connectCamera(hw_device_t** device)
{
......
if (camera_dev != NULL) {
/* Connect to the camera device. */
res = getCameraDevice()->connectDevice(); //V4L2CameraDevice 83
if (res == NO_ERROR) {
*device = &common;
}
}
return -res;
}
V4L2CameraDevice.cpp device/softwinner/common/hardware/camera/
83 status_t V4L2CameraDevice::connectDevice()
{
......
// open v4l2 camera device
int ret = openCameraDev(); //448
if (ret != OK)
{
return ret;
}
ret = cedarx_hardware_init(2);// CEDARX_HARDWARE_MODE_VIDEO
......
}
448 int V4L2CameraDevice::openCameraDev()
{
// open V4L2 device
Log.d(TAG, "dyyr - " + __FILE__ + ", " + __FUNCTION__);
mCamFd = open(mDeviceName, O_RDWR | O_NONBLOCK, 0); //至此完成打开底层设备全过程
if (mCamFd == -1)
{
LOGE("ERROR opening V4L interface: %s", strerror(errno));
return -1;
}
struct v4l2_input inp;
inp.index = mDeviceID;
if (-1 == ioctl (mCamFd, VIDIOC_S_INPUT, &inp))
{
LOGE("VIDIOC_S_INPUT error!\n");
return -1;
}
......
}
--------------------------------------------------------------------------
HAL层的配置文件camera.cfg device/softwinner/Dimond_97HD/camera.cfg, 读取配置: CCameraConfig.cpp, xxx()
下面是读取配置信息的一个例子:
CameraHardware.cpp device/softwinner/common/hardware/camera/
105 status_t CameraHardware::Initialize()
{
F_LOG;
if (mCameraConfig == NULL)
{
return UNKNOWN_ERROR;
}
initDefaultParameters(); //145
return NO_ERROR;
}
145 void CameraHardware::initDefaultParameters()
{
......
if (mCameraConfig->cameraFacing() == CAMERA_FACING_BACK) //根据配置信息设置XX
{
p.set(CameraHardware::FACING_KEY, CameraHardware::FACING_BACK);
LOGV("%s: camera is facing %s", __FUNCTION__, CameraHardware::FACING_BACK
);
}
else
{
p.set(CameraHardware::FACING_KEY, CameraHardware::FACING_FRONT);
LOGV("%s: camera is facing %s", __FUNCTION__, CameraHardware::
FACING_FRONT);
}
p.set(CameraHardware::ORIENTATION_KEY, 0);
......
}
HAL
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
gc0308.c drivers/media/video/sun4i_csi/device/gc0308.c
配置文件Sys_config1.fex Tools/pack/Chips/Sun4i/Configs/Crane/Dimod/Sys_config1.fex, 读取函数: ????????
Kernel
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

免责声明:文章转载自《学习Android camera笔记 &amp;amp; 调用流程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python任务调度模块 – APSchedulerBZOJ1103: [POI2007]大都市meg下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python中的多线程编程与暂停、播放音频的结合

先给两个原文链接: https://blog.csdn.net/u013755307/article/details/19913655 https://www.cnblogs.com/scolia/p/6132950.html 播放wav音频的原代码: #引入库 importpyaudio importwave importsys #定义数据流块...

【API】网络编程模型、多线程

1、网络通信编程 1)网络通信模型基础知识 TCP Server: WSAStartup() socket() bind() linsten() accept() send/recv() closesocket() WSACleanup() Client: WSAStartup() socket() c...

MFC 消息类型

---恢复内容开始--- 1、命令消息(WM_COMMAND) 所有派生自 CCmdTarget 的类都有资格接受WM_COMMAND。 2、Window消息(WM_xxx) 所有派生自 CWnd 的类都有资格接受 WM_xxx。 3、控件消息(WM_NOTIFY) 控件向其父窗口通知消息。 消息处理 1、WM_xxx 消息处理 窗口类(自身)处理→基类处...

mysql主从之多线程复制

多线程复制 mysql 主从复制原理: 1. master 节点上的binlogdump 线程,在slave 与其正常连接的情况下,将binlog 发送到slave 上。 2. slave 节点的I/O Thread ,通过读取master 节点binlog 日志名称以及偏移量信息将其拷贝到本地relay log 日志文件。 3. slave 节点的SQL...

Linux ${} 变量内容的提取和替换功能等

[root@localhost log]# var=/dir1/dir2/file.txt 1、对变量取值 [root@localhost log]# echo ${var} /dir1/dir2/file.txt 2、求字符串的长度 [root@localhost log]# echo ${#var} 19 3、提取位置3到最后的字符 [root@loc...

IOCP 浅析(java代码实现)

随着计算机技术,尤其是网络技术的飞速发展,如今的程序开发人员不仅仅局限于基于单机运行或单一线程的应用程序的开发。服务器端 / 客户端模式的最显著的特点是一个服务器端应用能同时为多个客户端提供服务。而传统的服务器端 / 客户端模式通常为每一个客户端创建一个独立的线程,这种实现方式在客户端数量不多的情况下问题不大,但对于类似于铁路网络订票这样的瞬间客户数量巨大...