Camera分析

来源:互联网 发布:关于大学生网络的论文 编辑:程序博客网 时间:2024/05/29 07:58
Ov5640.c (drivers\media\video) 830872013-5-31
两个地方使用到夜景,但都是关闭:
ov5640_config_preview
ov5640_set_night_mode(sd, 0);//关闭夜景


ov5640_config_capture
ov5640_set_night_mode(sd, 0);//关闭夜景


HAL层代码:
Broadcom21664/src/hardware/broadcom/rhea_hawaii/v4l2_camerahal/

App:
一、资源文件:
1.apps\camera\res\xml\Camera_preferences.xml 
    <IconListPreference
            camera:key="pref_camera_scenemode_key"
            camera:defaultValue="@string/pref_camera_scenemode_default"
            camera:title="@string/pref_camera_scenemode_title"
            camera:singleIcon="@drawable/ic_scn_holo_light"
            camera:entries="@array/pref_camera_scenemode_entries"
            camera:entryValues="@array/pref_camera_scenemode_entryvalues" />


2.apps\camera\res\values-en-rgb\Strings.xml
<string name="pref_camera_scenemode_title" msgid="1420535844292504016">"Scene mode"</string>


3.apps\camera\res\values\Arrays.xml 
    <string-array name="pref_camera_scenemode_entries" translatable="false">
        <item>@string/pref_camera_scenemode_entry_auto</item>
        <item>@string/pref_camera_scenemode_entry_landscape</item>
        <item>@string/pref_camera_scenemode_entry_portrait</item>
        <item>@string/pref_camera_scenemode_entry_night</item>
        <item>@string/pref_camera_scenemode_entry_night_portrait</item>
        <item>@string/pref_camera_scenemode_entry_action</item>
        <item>@string/pref_camera_scenemode_entry_theatre</item>
        <item>@string/pref_camera_scenemode_entry_beach</item>
        <item>@string/pref_camera_scenemode_entry_snow</item>
        <item>@string/pref_camera_scenemode_entry_sunset</item>
        <item>@string/pref_camera_scenemode_entry_steadyphoto</item>
        <item>@string/pref_camera_scenemode_entry_fireworks</item>
        <item>@string/pref_camera_scenemode_entry_sports</item>
        <item>@string/pref_camera_scenemode_entry_party</item>
        <item>@string/pref_camera_scenemode_entry_candlelight</item>
    </string-array>

    <string-array name="pref_camera_scenemode_entryvalues" translatable="false">
        <item>auto</item>
        <item>landscape</item>
        <item>portrait</item>
        <item>night</item>
        <item>night-portrait</item>
        <item>action</item>
        <item>theatre</item>
        <item>beach</item>
        <item>snow</item>
        <item>sunset</item>
        <item>steadyphoto</item>
        <item>fireworks</item>
        <item>sports</item>
        <item>party</item>
        <item>candlelight</item>
    </string-array>
由这些定义,我们可以看出,Android的Camera应用程序支持15种场景模式。但是硬件并非都支持这些模式的。所以最终的菜单中只会显示这15种场景模式当中底层硬件所支持的,如果硬件支持的场景模式与其中任何一种都不匹配,则不会显示出“Scene mode”菜单。


二、菜单的创建:
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);


        if (mIsImageCaptureIntent) {
            // No options menu for attach mode.
            return false;
        } else {
            addBaseMenuItems(menu);
        }
        return true;
    }
//这段代码没有看明白,以后分析。
在非Video Camera模式下,mIsImageCaptureIntent为true,此处将不做任何处理。当mIsImageCaptureIntent为false时,即Video Camera模式下,将调用函数addBaseMenuItems()来创建Video Camera的菜单。Picture大小的菜单不会出现在Video Camera模式下,所以就不对addBaseMenuItems()函数分析了。


既然这里没有创建Camera模式下的菜单,那Camera模式下的菜单在哪里创建的了?我们接着分析。在Camera.java文件中定义了类MainHandler,它里面只有一个成员函数handleMessage(),它用来处理Camera应用程序中的message。
代码:
    private class MainHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case RESTART_PREVIEW: {
                    restartPreview();
                    if (mJpegPictureCallbackTime != 0) {
                        long now = System.currentTimeMillis();
                        mJpegCallbackFinishTime = now - mJpegPictureCallbackTime;
                        Log.v(TAG, "mJpegCallbackFinishTime = "
                                + mJpegCallbackFinishTime + "ms");
                        mJpegPictureCallbackTime = 0;
                    }
                    break;
                }


                case CLEAR_SCREEN_DELAY: {
                    getWindow().clearFlags(
                            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                    break;
                }


                case FIRST_TIME_INIT: {
                    initializeFirstTime();
                    break;
                }


                case SET_CAMERA_PARAMETERS_WHEN_IDLE: {
                    setCameraParametersWhenIdle(0);
                    break;
                }
            }
        }
    }
Message FIRST_TIME_INIT应该在类Camera初始化时就会被处理,我是这样猜的,只是还没有找到具体的code。initializeFirstTime()的实现如下所示:
    private void initializeFirstTime() {
。。。
mHeadUpDisplay.setListener(new MyHeadUpDisplayListener());
        initializeHeadUpDisplay();//里面会对xml进行加载
        mFirstTimeInitialized = true;//前面初始化好之后将标志设置为true
        changeHeadUpDisplayState();
。。。
    }
上面有两个函数很重要:
1.加载监听器MyHeadUpDisplayListener
2.加载xml文件initializeHeadUpDisplay
    private void initializeHeadUpDisplay() {
        CameraSettings settings = new CameraSettings(this, mInitialParams,
                CameraHolder.instance().getCameraInfo());
        mHeadUpDisplay.initialize(this,
                settings.getPreferenceGroup(R.xml.camera_preferences),
                getZoomRatios(), mOrientationCompensation);
//其中R.xml.camera_preferences指的就是camera_preference.xml资源文件。
。。。
        updateSceneModeInHud();
    }
接下来我们将对settings.getPreferenceGroup()--->获取配置,mHeadUpDisplay.initialize()和MyHeadUpDisplayListener做以介绍。
函数settings.getPreferenceGroup()定义在文件Packages/apps/camera/src/com/android/camera/CameraSetting.java中。其具体定义为:
    public PreferenceGroup getPreferenceGroup(int preferenceRes) {
        PreferenceInflater inflater = new PreferenceInflater(mContext);
        PreferenceGroup group =
                (PreferenceGroup) inflater.inflate(preferenceRes);
        if (mParameters != null) initPreference(group);
        return group;
    }
函数inflater.inflate(preferenceRes)将camera_preference.xml文件中的菜单信息存储到PreferenceGroup中。接着函数initPreference()对这些信息做了处理
private void initPreference(PreferenceGroup group) {
。。。
ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);
。。。
        if (sceneMode != null) {
            filterUnsupportedOptions(group,
                    sceneMode, mParameters.getSupportedSceneModes());
        }
。。。
}
其中,宏定义KEY_SCENE_MODE定义在文件
Packages/apps/camera/src/com/android/camera/CameraSetting.java中,具体定义为:
public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key";
该值与camera_preference.xml中的KEY值匹配。语句ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);将sceneMode的信息存储在了结构体ListPreference sceneMode中。
语句
        if (sceneMode != null) {
            filterUnsupportedOptions(group,
                    sceneMode, mParameters.getSupportedSceneModes());
        }
mParameters.getSupportedSceneModes()获取了硬件Camera所支持的sceneMode信息,我在Camera HAL层(broadcom\rhea_hawaii\v4l2_camerahal\brcm\CameraHAL.cpp)的实现中,在函数initDefaultParameters()中设置了硬件所支持的sceneMode。CODE如下:
str8 = pCamDev->querySceneModes(defScene);//在这里需要进一步查看
if (str8.length() > 0) {//查询支持的scene mode
ALOGI("initDefaultParameters(): camera device supports %s scene modes", str8.string());
mParameters.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, str8.string());
mParameters.set(CameraParameters::KEY_SCENE_MODE, defScene.string());
}


函数filterUnsupportedOptions()会将Camera应用和硬件支持的Scence中两者匹配的mode存储在group中。


函数mHeadUpDisplay.initialize()定义在文件
broadcom_test_apps\brcmcamera\src\com\broadcom\camera\ui\CameraHeadUpDisplay.java中,其具体定义为:
    public void initialize(Context context, PreferenceGroup group,
            float[] initialZoomRatios, int initialOrientation) {
        mInitialZoomRatios = initialZoomRatios;
        mInitialOrientation = initialOrientation;
        super.initialize(context, group);
    }
调用父类的initialize
    public void initialize(Context context, PreferenceGroup preferenceGroup) {
        mPreferenceGroup = preferenceGroup;
        mSharedPrefs = ComboPreferences.get(context);
        mPopupWindow = null;
        clearComponents();
        initializeIndicatorBar(context, preferenceGroup);
        requestLayout();
    }
其中函数initializeIndicatorBar()定义如下:
    protected void initializeIndicatorBar(
            Context context, PreferenceGroup group) {
        mIndicatorBar = new IndicatorBar();


        mIndicatorBar.setBackground(new NinePatchTexture(
                context, R.drawable.ic_viewfinder_iconbar));
        mIndicatorBar.setHighlight(new ColorTexture(COLOR_ICONBAR_HIGHLIGHT));
        addComponent(mIndicatorBar);
        mIndicatorBar.setOnItemSelectedListener(new IndicatorBarListener());
    }
函数addComponent()将group中的picture大小添加到了菜单中。至此,菜单的创建就告一段落。