1. 程式人生 > >UVC系列5-編寫Android jni程式碼實現控制PTZ

UVC系列5-編寫Android jni程式碼實現控制PTZ

Android kernel層完成定製之後,需要寫app實現對攝像頭的控制,主要通過jni程式碼實現。

jni程式碼中主要定義這幾個函式:

jintArrayJava_com_chuck_android_uvccamera_MainActivity1_startControlCamera(JNIEnv*env,jobject thiz , jint controlId ,jint value)

實現控制的主函式

jintJava_com_chuck_android_uvccamera_MainActivity1_getCurrentControlValue

實現獲取當前控制引數的值

jbooleanJava_com_chuck_android_uvccamera_UVCCameraPreview_isSupportPtz

判斷當前攝像頭是否支援PTZ控制。

現在逐個函式說明,startControlCamera函式如下:

這裡的controlId就是我們在kernel新增的idvalue就是每個控制id對應的值,值要按照UVC協議規定的傳遞。

接下來看看startControlPanTilt函式:

可以看到控制的核心函式是linuxioctl,傳入的引數是v4l2_control,這個結構體裡面有什麼東西呢,可以看看其定義(https://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html#v4l2-control):

結構體裡面就idvalue,按照UVC協議賦值,其他的交給ioctrl就可以了。此時ioctrl到了底層到了哪裡呢?其實到了drivers/media/usb/uvc/uvc_v4l2.c檔案中的uvc_v4l2_do_ioctl方法,在這個方法中需要關注的是以下幾行程式碼:

v4l2_prio_check應該是檢查是否有執行的優先順序,沒有執行的優先順序的話返回當前繁忙裝置,如下:

int v4l2_prio_check(struct v4l2_prio_state*global, enum v4l2_priority local)

{

         return(local < v4l2_prio_max(global)) ? -EBUSY : 0;

}

接下來的執行順序與資料庫的插入操作比較類似,開始執行控制,設定相關引數,檢查控制結果,失敗的話回滾操作,否則提交執行,同時記住當前的設定值。

第二個需要關注的是實現獲取當前控制引數,getControlValue,有兩種寫法,一種是不用迴圈,一種是迴圈遍歷UVC控制引數,檢視裝置當前控制引數的值,如下:

這裡獲取控制id當前的值也是在drivers/media/usb/uvc/uvc_v4l2.cuvc_v4l2_do_ioctl方法中,其中使用的獲取引數是VIDIOC_G_EXT_CTRLS,其實查詢單個控制引數的值用VIDIOC_G_CTRL也可以,只不過VIDIOC_G_EXT_CTRLS是多個控制引數一起查詢,在底層原始碼裡面是迴圈遍歷查詢,而VIDIOC_G_CTRL是直接查詢,相關原始碼如下:

 有關v4l2_ext_controlsv4l2_ext_control的控制引數見下圖:

現在看看判斷當前攝像頭是否支援PTZ控制的函式,實際上是遍歷攝像頭的控制id,檢視是否有PTZ相關的控制id,函式中定義的幾個變數值定義如下:

const char* CONTROL_FLAG_PAN = "Pan(Absolute)";

const char* CONTROL_FLAG_TILT = "Tilt(Absolute)";

const char* CONTROL_FLAG_ZOOM = "Zoom,Absolute";

const int PAN_SPEED_ID = 10094880;

const int TILT_SPEED_ID = 10094881;

const int ZOOM_RELATIVE_ID = 10094863;

詳細的函式如下:

這裡可以看到這個函式裡面詳細輸出了支援哪些控制引數,各個控制引數的最大值,最小值,步長等資訊,這些查詢最後在底層的呼叫是在drivers\media\usb\uvc\uvc_ctrl.c__uvc_query_v4l2_ctrl函式中,具體的描述在前一篇文章中有詳細的講述。

上述程式碼編寫完畢,寫MK檔案,如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := UVCCamera

LOCAL_SRC_FILES := UVCCamera_Rel.cpp

LOCAL_LDLIBS    := -llog -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

app層的程式碼編寫完畢,在AS中編譯執行生成so檔案,在app中就可以使用了。同時要注意的是,這個app的許可權級別要比較高,不然可能沒有許可權執行ioctrl

另外這個程式碼中還涉及到了開啟/dev/video0檔案的操作,如下:

至此,android UVC控制雲臺攝像頭系列完成,在整個方案研發的過程中最大的阻礙是android kernel不支援相對控制,需要搜尋相關資料自己去打patch,打了patch之後還要不斷的除錯試錯;另外一個阻礙是攝像頭廠商不同UVC版本的攝像頭,讓android適配的過程中吃盡苦頭,如果碰上樂於合作的廠商問題就會很快解決。在這個技術實現的過程中深刻體會到有時候不逼自己一把,都不知道自己有多大的潛力。

在這個過程中涉及到了kernel層原始碼的解讀,kernel原始碼的修改和除錯,kernel層的編譯和打包刷機,android jni程式碼等,整個過程還有boss每天一次的問候,查詢進度。

微信公眾號:Android部落格

相關推薦

UVC系列5-編寫Android jni程式碼實現控制PTZ

在Android kernel層完成定製之後,需要寫app實現對攝像頭的控制,主要通過jni程式碼實現。 在jni程式碼中主要定義這幾個函式: jintArrayJava_com_chuck_android_uvccamera_MainActivity1_startC

Android 通過程式碼實現控制資料網路的開關(僅適用於5.0以上)

Android 5.0以前使用ConnectivityManager通過反射兩個方法setMobileDataEnabled和getMobileDataEnabled來控制行動網路開和關。  Android 5.0以後使用TelephonyMananger類通過反射獲取setDataEna

Android 通過程式碼實現控制資料網路的開關(僅適用於5.0以上)

Android 5.0以前使用ConnectivityManager通過反射兩個方法setMobileDataEnabled和getMobileDataEnabled來控制行動網路開和關。  Android 5.0以後使用TelephonyMananger類通過反射獲取set

Android的NDK開發(5)————Android JNI實現檔案的read、write與seek操作

/********************************************************************************************  * author:conowen@大鐘                      

Django-website 程序案例系列-5 模態對話框實現提交數據

-i posit class one utf obj select val value html代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-

Android studio程式碼實現打電話+點選事件四種方式

?Android系統架構(重點) 第一層:應用層Application 第二層:應用框架層Application Framework 第三層:Android底層類庫層 Libraries、Dalvik虛擬機器 第四層:linux核心層 linux kernel Android是執行在

React Native呼叫Android原生程式碼實現車牌識別功能【附效果圖附原始碼】

        這段時間研究了下React Native,Facebook推出的,結合了Web應用和Native應用的優勢,可以使用JavaScript來開發iOS和Android原生應用,決定簡單研究下,於是開始搭建環境,編寫HelloWorld,完成後又覺得HelloWo

Android JNI HelloWorld實現

建立一個JNIDemo的Android工程在專案下建立一個資料夾jni。(注意必須是jni目錄)在jni目錄下建立兩個檔案:Android.mk 和 first_jni.c(.c檔案的名字可以任意)編寫Android.mk檔案:(參見Demo當中的Androd.mk檔案)LOCAL_MODULE := fir

【iOS 0 行程式碼系列】之 0 行程式碼實現TableView,CollectionView無資料佔位圖與文字

如果你還沒有看過下面的文章,可以花點時間看看 >>>>>1.一行程式碼完成“空TableView佔位檢視”管理: 原理: 1.獲取 Section 的數量 2.

android程式碼實現截圖功能(靜態+動態視訊)

分享下靜態截圖的功能程式碼: public class ScreenShot { // 獲取指定Activity的截圖,儲存到png檔案 static Bitmap takeScreenShot(Activity activity) { L

Android JNI實現檔案的read、write與seek操作

轉自:http://blog.csdn.net/conowen/article/details/7525837 /*******************************************************************************

Android jni程式碼註冊本地方法

Android 開發中有時需要呼叫本地方法,這就需要註冊本地方法,而註冊的方法有兩種: RegisterNatives註冊使用javah生成規範的標頭檔案,然後編寫對應的原始檔。先看一下java檔案

HDFS的JAVA客戶端編寫(JAVA程式碼實現對HDFS的操作)

原始碼如下: package com.sfd.hdfs; import java.io.FileInputStream; import java.io.IOException; import org.apache.commons.compress.ut

android 使用程式碼實現 RelativeLayout佈局!

使用 AbsoluteLayout 可以直接指定其子 View 的絕對位置, 這種佈局方式雖然簡單,但是不夠靈活。比如在一個程式中,按鈕2 位於 按鈕1 的下方且和 按鈕1 左對齊,我們可以使用指定兩個按鈕的絕對位置的方式佈局,但是當佈局完成後,由於某些原因,這兩個按鈕需要

Android使用程式碼實現左右半圓的按鈕背景

即使得到本人許可,也不許轉載! 其實特別簡單,用xml寫一個shape,把radius寫一個特別大的值即可,比如100dp,總之肯定比你的按鈕最大值大就可以。 下面是效果圖 xml程式碼如下:

css程式碼實現控制圖片顏色或者改變圖片顏色

1、黑色純色,背景白色的圖片 .pic1 { background-image: url($img), linear-gradient(#f00, #f00); //純色漸變 background-blend-mode: lighten; background-s

[ 一起學React系列 -- 5 ] 如何優雅得使用表單控制元件

網頁中使用的form表單大家肯定都再熟悉不過了,它主要作用是用來收集和提交資訊。React中的表單元件與我們普通的Html中的表單及其表現形式沒有什麼不同,所以如何使用表單我覺得再拿出來說可能是畫蛇添足、毫無意義。不過再怎麼樣也不能辜負大家對標題的期待吧,本篇內容筆

Android四大元件應用系列5——使用AIDL實現跨程序呼叫Service

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstan

Office 365實現單點登錄系列(5)—配置單點登錄

-m col 詳細介紹 運行 環境搭建 可以登錄 rate 目錄同步 tof 這是單點登錄系列的最後一篇文章,前面4篇文章其實都是在為這篇文章的內容做準備,我把這四篇文章的鏈接放在下面,如果大家有需要,可以參考我以下的鏈接: Office 365實現單點登錄系列(1)—域環

從 0 到 1 實現 React 系列 —— 5.PureComponent 實現 && HOC 探幽

相等 true 同時 connect es6 控制臺顯示 共享 ppr func 本系列文章在實現一個 cpreact 的同時幫助大家理順 React 框架的核心內容(JSX/虛擬DOM/組件/生命周期/diff算法/setState/PureComponent/HOC/.