android camera jni调用
http://www.mamicode.com/info-detail-1002139.html
how to compile library of native camera for android ndk? http://stackoverflow.com/questions/22859299/how-to-use-library-of-native-camera-for-android-ndk
Android Camera 采用C/S架构,client 与server两个独立的线程之间(CameraService)使用Binder通信。
一 CameraService的注册。
1.手机开机后,会走init.rc流程,init.rc会启动MediaServer Service。
service media /system/bin/mediaserver
class main
user root ####
# google default ####
# user media ####
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm media sdcard_r system net_bt_stack ####
# google default ####
# group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm #### ioprio rt 4
2.MediaServer的main函数位于frameworks/base/media/mediaserver/main_mediaserver.cpp中。
在Main_MediaServer.cpp的main函数中,CameraService完成了注册
1 int main(int argc __unused, char** argv)
2 {
3 signal(SIGPIPE, SIG_IGN);
4 char value[PROPERTY_VALUE_MAX];
5 bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
6 pid_t childPid;
7 ..............................
8 sp<ProcessState> proc(ProcessState::self());
9 sp<IServiceManager> sm = defaultServiceManager();
10 ALOGI("ServiceManager: %p", sm.get());
11 AudioFlinger::instantiate();
12 MediaPlayerService::instantiate();
13 #ifdef MTK_AOSP_ENHANCEMENT
14 MemoryDumper::instantiate();
15 #endif
16 CameraService::instantiate();
17 ......................................
3. instantiate的实现在CameraService的父类中,
namespace android {
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
static void publishAndJoinThreadPool(bool allowIsolated = false) {
publish(allowIsolated);
joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() { return NO_ERROR; }
private:
static void joinThreadPool() {
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
}
};
}; // namespace android
可以发现在publish()函数中,CameraService完成服务的注册 。SERVICE是个模板,这里是注册CameraService,所以可用CameraService代替
return sm->addService(String16(CameraService::getServiceName()), new CameraService());
这样,Camera就在ServiceManager完成服务注册,提供给client随时使用。
二 client如何连上server端,并打开camera模块
我们从Camera.open()开始往framework进行分析,调用frameworks\base\core\java\android\hardware\Camera.java类的open方法 。
public static Camera open() {
............................................
return new Camera(cameraId);
.............................................
}
这里调用了Camera的构造函数,在构造函数中调用了cameraInitVersion
private int cameraInitVersion(int cameraId, int halVersion) {
..................................................
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
}
此后进入JNI层android_hardware_camera.cpp
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
.......................
camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
...................... sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
...........................
camera->setListener(context);
.......................... }
JNI函数里面,我们找到Camera C/S架构的客户端了(即红色加粗的那个Camera),它调用connect函数向服务端发送连接请求。JNICameraContext这个类是一个监听类,用于处理底层Camera回调函数传来的数据和消息
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
status_t status = NO_ERROR;
const sp<ICameraService>& cs = getCameraService(); if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera: %d", cameraId);
c.clear();
}
return c;
}
// establish binder interface to camera service
template <typename TCam, typename TCamTraits>
const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16(kCameraServiceName));
if (binder != 0) {
break;
}
ALOGW("CameraService not published, waiting...");
usleep(kCameraServicePollDelay);
} while(true);
if (gDeathNotifier == NULL) {
gDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(gDeathNotifier);
gCameraService = interface_cast<ICameraService>(binder);
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
此处终于获得CameraService实例了,该CameraService实例是通过binder获取的。
再来看fnConnectService是什么,
在Camera.cpp中,有
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
&ICameraService::connect;
这样也就是说fnConnectService就是使用CameraService调用connect,从这里开始,终于从进入了服务端的流程:
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) { .........................
status_t status = validateConnect(cameraId, /*inout*/clientUid);
.................................. if (!canConnectUnsafe(cameraId, clientPackageName,
cameraClient->asBinder(),
/*out*/clientTmp)) {
return -EBUSY;
} status = connectHelperLocked(/*out*/client,
cameraClient,
cameraId,
clientPackageName,
clientUid,
callingPid);
return OK;
}
status_t CameraService::connectHelperLocked(
/*out*/
sp<Client>& client,
/*in*/
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
int callingPid,
int halVersion,
bool legacyMode) { ....................................
client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(), legacyMode);
....................................
status_t status = connectFinishUnsafe(client, client->getRemote());
............................................
}
在connectHelpLocked,CameraService返回一个其实是它内部类的client——CameraClient。(注意此client是CameraService内部的CameraClient,不是Camera客户端)
在connectFinishUnsafe中,
status_t status = client->initialize(mModule);
我们再来看CameraClient类的initialize函数
status_t CameraClient::initialize(camera_module_t *module) {
int callingPid = getCallingPid();
status_t res;
mHardware = new CameraHardwareInterface(camera_device_name);
res = mHardware->initialize(&module->common);
}
CameraClient的初始化就是:先实例化Camera Hal接口 CameraHardwareInterface,CameraHardwareInterface调用initialize()进入HAL层打开Camera底层驱动
status_t initialize(hw_module_t *module)
{
ALOGI("Opening camera %s", mName.string());
camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
camera_info info;
status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
if (res != OK) return res; int rc = OK;
if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
// Open higher version camera device as HAL1.0 device.
rc = cameraModule->open_legacy(module, mName.string(),
CAMERA_DEVICE_API_VERSION_1_0,
(hw_device_t **)&mDevice);
} else {
rc = CameraService::filterOpenErrorCode(module->methods->open(
module, mName.string(), (hw_device_t **)&mDevice));
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();
return rc;
}
hardware->initialize(&mModule->common)中mModule模块是一个结构体camera_module_t,他是怎么初始化的呢?我们发现CameraService里面有个函数
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef(); if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&mModule) < 0) {
LOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
} }
了解HAL层的都知道hw_get_module函数就是用来获取模块的Hal stub,这里通过CAMERA_HARDWARE_MODULE_ID 获取Camera Hal层的代理stub,并赋值给mModule,后面就可通过操作mModule完成对Camera模块的控制。那么onFirstRef()函数又是何时调用的?
onFirstRef()属于其父类RefBase,该函数在强引用sp新增引用计数时调用。就是当 有sp包装的类初始化的时候调用,那么camera是何时调用的呢?可以发现在
客户端发起连接时候
sp Camera::connect(int cameraId)
{
LOGV("connect");
sp c = new Camera();
const sp& cs = getCameraService();
}
这个时候初始化了一个CameraService实例,且用Sp包装,这个时候sp将新增计数,相应的CameraService实例里面onFirstRef()函数完成调用。
CameraService::connect()即实例化CameraClient并打开驱动,返回CameraClient的时候,就表明客户端和服务端连接建立。Camera完成初始化。
参考文档:
Android 4.0 Camera架构分析之Camera初始化 http://blog.csdn.net/dnfchan/article/details/7594590
Android 5.1 Camera Framework源码
android camera jni调用的更多相关文章
- [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so
0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...
- [置顶] android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so
0:前言 1:本文主要作为丙方android公司的身份来写 2:作者有不对的地方,请指出,谢谢 [第一篇:android利用jni调用第三方库——编写库libhello.so] [第二篇:androi ...
- Android的JNI调用(二)
Android Studio 2.3在native下已经有了代码提示功能,按照提示下载相应组件就可以debug native代码. 一.Java调用JNI与JNI调用Java 1.1 C调用Java ...
- (AIDE)Android Eclipse JNI 调用 .so文件加载问题
背景:对于Android工程 Eclipse里编译好的.so文件放到 libs\armeabi下以后, 这样.so文件就可以打包到apk文件里,在apk装到手机上以后 在libs\armeabi下的. ...
- Android通过JNI调用驱动程序(完全解析实例)
要达到的目的:android系统中,用JAVA写界面程序,调用jni中间库提供的接口,去操作某个驱动节点,实现read,writer ioctl等操作!这对底层驱动开发人员是很重要的一个调试通道,也是 ...
- 【转】Android通过JNI调用驱动程序(完全解析实例)
原文网址:http://blog.csdn.net/ok138ok/article/details/6560875 要达到的目的:android系统中,用JAVA写界面程序,调用jni中间库提供的接口 ...
- Android于JNI调用列出的程序
1.安装和下载cygwin,下载Android NDK: 2.于ndk工程JNI接口设计: 3.采用C/C++实现本地方法. 4.JNI生成动态链接库.so档: 5.动态链接库副本javaprojec ...
- Android的JNI调用(一)
Android提供NDK开发包来提供Android平台的C++开发,用来扩展Android SDK的功能.主要包括Android NDK构建系统和JNI实现与原生代码通信两部分. 一.Android ...
- android studio jni调用入门
一.开发环境配置: 1.Android Studio 2.3.3 2.android-ndk-r14b-windows-x86_64 二.创建项目 1.新建android项目 2.新建文件 3.编译生 ...
随机推荐
- 15:开发Rsync服务启动脚本案例
[root@m01 ~]# rsn_count="ps -ef|grep 'rsync --d[a]emon'|wc -l" [root@m01 ~]# echo ${rsn_co ...
- 深度历险:Redis 内存模型详解
https://mp.weixin.qq.com/s/Gp6Ur7omGY6ZqDWygU2meQ Redis 是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说 Redi ...
- js实现点击定位最顶端
//------------------------------------点击按钮------------------------------------ <span onClick=&quo ...
- 苯(Benzene)
在常温下是甜味.可燃.有致癌毒性的无色透明液体,其密度小于水,但分子质量大于水,并带有强烈的芳香气味.它难溶于水,易溶于有机溶剂,本身也可作为有机溶剂.苯是一种石油化工基本原料,其产量和生产的技术水平 ...
- python 爬虫2 Urllib库的高级用法
1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. import url ...
- git Staging Deleted files
Use git rm foo to stage the file for deletion. (This will also delete the file from the file system, ...
- js yield
meikidd 发布在meikidd2015年5月6日view:3397 在文章任何区域双击击即可给文章添加[评注]!浮到评注点上可以查看详情. 隐藏标注 首先请原谅我的标题党(●—●),tj 大神的 ...
- Classification week2: logistic regression classifier 笔记
华盛顿大学 machine learning: Classification 笔记. linear classifier 线性分类器 多项式: Logistic regression & 概率 ...
- 看懂Gradle脚本(4)- Groovy语法之运算符重载
继续讨论Task定义 回想一下前一篇文章的样例: task myTask { doLast { println 'hello world!' } } 这段脚本定义了一个名为myTask的任务.而且通过 ...
- Lucene索引文件组成
Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙. 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程, ...