Analysis of Qualcomm 8X camera daemon Process

Source: Internet
Author: User
Tags message queue mutex

Camera

Let's take a look at the main flow of the abstraction layer:

Start a daemon process First

int Qcamsvr_start (void) (QCAMSVR.C)

{

1. server_fd = Open (Server_dev_name, O_RDWR);//Open the file node for the service

2. if (Mctl_load_comps ())//load all required components

3. rc = Qcamsvr_load_gesture_lib (&gesture_info.gesture_lib);//Load Gesture Library

4. ez_server_socket_id = Eztune_setup_server ("127.0.0.1", "55555");

if (pipe (ez_cmd_pipe)

ez_prev_server_socket_id = Eztune_setup_server ("127.0.0.1", "55556");

if (pipe (ez_prev_cmd_pipe)

Create two socket ports and set up two pipe files to monitor two ports

5. if (Get_mctl_node_info (SERVER_FD, &mctl_node_info))//access information about the service via the service node

{

This gets the sensor node information that is registered in the kernel called Msm_sensor_register ()

}

6. Sub.type = V4l2_event_all;

rc = IOCTL (SERVER_FD, vidioc_subscribe_event, &sub);//subscribe to all events via the IOCTL interface of the service device file

7. config_arg.server_fd = SERVER_FD;

CONFIG_ARG.EZ_READ_FD = ez_cmd_pipe[0];

CONFIG_ARG.EZ_WRITE_FD = ez_cmd_pipe[1];

CONFIG_ARG.EZ_PREV_READ_FD = ez_prev_cmd_pipe[0];

CONFIG_ARG.EZ_PREV_WRITE_FD = ez_prev_cmd_pipe[1];//Initialization of parameters for the configuration thread

8. Here is a loop that poll the files

do {

FDS[0].FD = SERVER_FD;

Fds[0].events = Pollpri;

FDS[1].FD = ez_server_socket_id;

Fds[1].events = Pollin;

FDS[2].FD = ez_prev_server_socket_id;

Fds[2].events = Pollin;

rc = Poll (FDS, 3, TIMEOUTMS);

if (Fds[0].revents & Pollpri) {/* Server Node Wake up *

Monitor the service's device files and create a configuration thread as soon as an open event is encountered

rc = Qcamsvr_process_server_node_event (&config_arg, &mctl_node_info,

&gesture_info);

}

The line surface is the monitoring and processing of two socket processes .

if ((fds[1].revents & pollin) = = Pollin) {/* EzTune Server */

int client_socket_id;

client_socket_id = Accept (ez_server_socket_id,

(struct sockaddr *) &addr_client_inet, &addr_client_len);

Write (ez_cmd_pipe[1], &client_socket_id, sizeof (int));

}

}

if ((fds[2].revents & pollin) = = Pollin) {/* EzTune Prev Server */

int client_socket_id;

client_socket_id = Accept (ez_prev_server_socket_id,

(struct sockaddr *) &addr_client_inet, &addr_client_len);

Write (ez_prev_cmd_pipe[1], &client_socket_id, sizeof (int));

}

}

}/* Else for Poll RC */

} while (1);

}

Below goes the process of configuring thread creation:

Take out the events generated by the service node, and then distribute them to separate master control threads based on the name of the configuration node

1. static int qcamsvr_process_server_node_event ()

{

command to process the event out queue of the service module

rc = IOCTL (CONFIG_ARG->SERVER_FD, vidioc_dqevent, &v4l2_evt);

if (V4l2_evt.type = = V4l2_event_private_start + msm_ges_resp_v4l2)

{

If it is a gesture event, a series of processing

if (Ctrl->type = = Msm_v4l2_ges_open) {

To set the interface for a master thread

P_gesture_info->cam_mctl.svr_ops.launch_mctl_thread =

Create_v4l2_conf_thread;

To set the exit interface for a master thread

P_gesture_info->cam_mctl.svr_ops.release_mctl_thread =

Destroy_v4l2_cam_conf_thread;

To set the camera enable

P_gesture_info->cam_mctl.svr_ops.camera_available =

qcamsvr_camera_available;

Set file handles for service device files

P_GESTURE_INFO->CAM_MCTL.SVR_OPS.SERVER_FD = config_arg->server_fd;

Create a gesture service

Status = P_gesture_info->gesture_lib.gesture_service_create (

&p_gesture_info->cam_mctl, &p_gesture_info->observer);

}

else if (Ctrl->type = = Msm_v4l2_ges_close) {

Vanishing gesture Service

Status = P_gesture_info->gesture_lib.gesture_service_send_data (ctrl)

}

if (status = = Camera_success) &&

(Ctrl->type! = msm_v4l2_ges_close)) {

If successful and the file is open, send data to the gesture service

Status = P_gesture_info->gesture_lib.gesture_service_send_data (ctrl);

if (Status! = camera_success) {

LOGE ("Gesture_service_send_data failed");

}

} else {

if (Ctrl->type = = Msm_v4l2_ges_close) {

Ctrl->status = cam_ctrl_success;

} else {

LOGE ("Gesture Send failure message");

Ctrl->status = cam_ctrl_failed;

}

Feedback the results of the operation to the camera service

V4l2_ioctl.ioctl_ptr = CTRL;

Qcamsvr_send_ctrl_cmd_done (CONFIG_ARG->SERVER_FD, &v4l2_ioctl);

If it is a camera event, a series of processing

}

else if (V4l2_evt.type = = V4l2_event_private_start + msm_cam_resp_v4l2)

{

if (Ctrl->type = = Msm_v4l2_open) {

Some initialization work through the pipe

To create a core thread

if (Tmp_mctl_struct->handle =

Feedback results to the camera server

Ctrl->status = cam_ctrl_success;

V4l2_ioctl.ioctl_ptr = CTRL;

Qcamsvr_send_ctrl_cmd_done (CONFIG_ARG->SERVER_FD, &v4l2_ioctl);

}

else if (Ctrl->type = = Msm_v4l2_close) {

Do some dying work

By writing some pipe

if (Destroy_v4l2_cam_conf_thread (Tmp_mctl_struct->handle) < 0)//extinct only thread

Ctrl->status = cam_ctrl_success;

V4l2_ioctl.ioctl_ptr = CTRL;

Feedback results to the camera service

Qcamsvr_send_ctrl_cmd_done (CONFIG_ARG->SERVER_FD, &v4l2_ioctl);

}

else {

Write some commands through the pipe and wait for the configuration to return

}

}

Let's take a look at just the thread creation function

void *create_v4l2_conf_thread (struct config_thread_arguments* arg)

{

The core job is to create a thread

rc = Pthread_create (&pme->cam_mctl_thread_id, NULL, Cam_mctl_thread, PME);

}

The following goes into the main function of the created configuration thread:

static void *cam_mctl_thread (void *data) (MCTL.C)

{

First initialize the file handle that needs to be monitored

PIPE_READFD = arg->read_fd;

PIPE_WRITEFD = arg->write_fd;

SERVER_FD = arg->server_fd;

EZ_PIPE_READFD = arg->ez_read_fd;

EZ_CLIENT_FD =-1;

EZ_PREV_PIPE_READFD = arg->ez_prev_read_fd;

EZ_PREV_CLIENT_FD =-1;

Monitor all events to the corresponding configuration node (this file handle specifically identifies what the meaning is not yet clear)

Sub.type = V4l2_event_all;

rc = IOCTL (CAM_FD, vidioc_subscribe_event, &sub);

The following begins the monitoring of the loop

do {

File Handle Initialization

FDS[0].FD = CAM_FD;

Fds[0].events = Pollpri;

FDS[1].FD = PIPE_READFD;

fds[1].events = Pollpri | Pollin;

FDS[2].FD = EZ_PIPE_READFD;

Fds[2].events = Pollin;

FDS[3].FD = EZ_CLIENT_FD;

Fds[3].events = Pollin;

FDS[4].FD = EZ_PREV_PIPE_READFD;

Fds[4].events = Pollin;

FDS[5].FD = EZ_PREV_CLIENT_FD;

Fds[5].events = Pollin;

/* Evt/msg from Qcam server */

if (Ctrl->type = = Msm_v4l2_close) {

Close all Resources

CONFIG_SHUTDOWN_PP (Pme->p_cfg_ctrl);

Feedback results to the service

rc = Mctl_send_ctrl_cmd_done (Pme->p_cfg_ctrl, NULL, TRUE);

}

else {

This function handles the corresponding command for the user control's app

if (Mctl_proc_v4l2_request (PME, CTRL) < 0)

}

/* evt/msg from config node */

rc = IOCTL (CAM_FD, vidioc_dqevent, &v4l2_event);//command to queue the event out

if (V4l2_event.type = =

V4l2_event_private_start + msm_cam_resp_div_frame_evt_msg) {

process -corresponding frame transfer

Mctl_pp_divert_frame (P_cfg_ctrl,

(void *) & (Event_data.isp_data.div_frame));

}else if (V4l2_event.type = =

V4l2_event_private_start + msm_cam_resp_mctl_pp_event) {

Handling post-event events

Mctl_pp_proc_event (P_cfg_ctrl,

(void *) & (Event_data.isp_data.pp_event_info));

}

else if (V4l2_event.type = =

V4l2_event_private_start + msm_cam_resp_stat_evt_msg) {

Handling of normal event messages

Mctl_proc_event_message (PME, ISP_ADSP);

}

else {

Cdbg_high ("%s:error:should not being Here", __func__);

}

/* Evt/msg from Eztune pipe */

if (ez_client_fd > 0)

Mctl_eztune_server_connect (PME, EZ_CLIENT_FD);

/* Evt/msg from Eztune client */

if (ez_client_fd > 0) {

Mctl_eztune_read_and_proc_cmd (Ez_mctl_socket_cmd);

/* evt/msg from Eztune prev Pipe */

if (ez_prev_client_fd > 0)

Mctl_eztune_prev_server_connect (PME, EZ_PREV_CLIENT_FD);

}

/* evt/msg from Eztune prev Client */

if ((fds[5].revents & pollin) = = Pollin) {

if (ez_prev_client_fd > 0) {

Mctl_eztune_read_and_proc_cmd (Ez_mctl_prev_socket_cmd);

}

}

}wile (TRUE)

End of loop unsubscribe all messages

if (IOCTL (CAM_FD, Vidioc_unsubscribe_event, &sub) < 0)

}

Let's take a look at the interface of camera in the hardware abstraction layer:

The main point is three:

1. Preview: Previewing

2. Recording video

3. Picture photo

Module interface functions:

Get_number_of_cameras:get_number_of_cameras,

Get_camera_info:get_camera_info,

camera_info_t:

typedef struct {

int modes_supported;//Supported mode

int8_t CAMERA_ID;//ID logo

Cam_position_t position;//before or after the camera

uint32_t sensor_mount_angle;//Angle

}camera_info_t;

We currently use the Qualcomm 8X platform:

Camera module:

This module has a global instance of the camera service structure that is used to globally manage various subsystem devices.

subsystem devices are common:

Enum Msm_cam_subdev_type {

Csiphy_dev,

Csid_dev,

Csic_dev,

Ispif_dev,

Vfe_dev,

Axi_dev,

Vpe_dev,

Sensor_dev,

Actuator_dev,

Eeprom_dev,

Gesture_dev,

};

Define an abstract camera service device:

struct Msm_cam_server_dev {

/* Config node device*/

struct Platform_device *server_pdev;

/* server node V4L2 device */

struct V4l2_device V4l2_dev;

struct Video_device *video_dev;

struct Media_device Media_dev;

/* Info of sensors successfully probed*/

struct Msm_camera_info camera_info;

/* Info of configs successfully created*/

struct Msm_cam_config_dev_info config_info;

/* Active working camera device-only one allowed at the This time*/

struct Msm_cam_v4l2_device *pcam_active;

/* Number of camera devices opened*/

atomic_t number_pcam_active;

struct V4l2_queue_util server_command_queue;

/* This queue used by the config thread to send responses back to the

* Control Thread. It is accessed only from a process context.

*/

struct Msm_cam_server_queue Server_queue[max_num_active_camera];

uint32_t server_evt_id;

struct Msm_cam_server_mctl_inst Mctl[max_num_active_camera];

uint32_t mctl_handle_cnt;

int use_count;

/* All the registered ISP subdevice*/

struct Msm_isp_ops *isp_subdev[msm_max_camera_configs];

/* Info of MCTL nodes successfully probed*/

struct Msm_mctl_node_info mctl_node_info;

struct Mutex server_lock;

struct Mutex server_queue_lock;

/*v4l2 subdevs*/

struct V4l2_subdev *csiphy_device[max_num_csiphy_dev];

struct V4l2_subdev *csid_device[max_num_csid_dev];

struct V4l2_subdev *csic_device[max_num_csic_dev];

struct V4l2_subdev *ispif_device;

struct V4l2_subdev *vfe_device[max_num_vfe_dev];

struct V4l2_subdev *axi_device[max_num_axi_dev];

struct V4l2_subdev *vpe_device[max_num_vpe_dev];

struct V4l2_subdev *gesture_device;

};

The process of the next camera is analyzed from the perspective of the control flow.

First, the camera initiates a daemon process to perform the core operation.

Where to start the daemon process :

In the Init.target.rc file

#start Camera Server as Daemon

Service Qcamerasvr/system/bin/mm-qcamera-daemon

Class Late_start

User System

Group System Camera inet

Where this Mm-qcamera-daemon bin file is generated:

Android\vendor\qcom\proprietary\mm-camera\apps\appslib\android.mk

This MK file generates the Mm-qcamera-daemon bin file

Entry function for Daemon process : Mian () (CAMDAEMON.C)

A camera daemon in the init process , opens a service

This thread is associated with a specific sensor and is responsible for the specific details of the sensor operation

This is the main thread of the daemon process , which collects events from server node, issues mctl thread, queues with the server node based on the name of Config, keeps polling its event queue, gets command, and handles global processing

Mctl_pp_poll_thread

Mctl thread

Main daemon Thread

Daemon

This thread communicates with the Config node in the kernel, receives a command in the message queue of the polling node, and processes it globally

(each config node corresponds to a mctl thread)

The approximate process of abstraction layer to kernel layer:

The abstraction layer will command down to the kernel through server node and Config node, and the corresponding node driver will manage the command through the event queue.

The daemon process , by opening the corresponding thread, keeps polling the event queue and handles the command on the upper level.

Important tasks in main daemon thread:

One: Load the hardware components associated with the sensor operation, and load some necessary libraries to pave the environment for the camera's formal work:

①axi_comp_create

②sensor_comp_create

③flash_led_comp_create

④flash_strobe_comp_create

⑤camif_comp_create

⑥vfe_comp_create

⑦actuator_comp_create

⑧eeprom_comp_create

⑨mctl_load_stats_proc_lib

⑩mctl_load_frame_proc_lib

Two Looping work for threads

threads, as the name implies, must have a closed loop body, doing some core operations in the loop body

While the main thread of the daemon process Polls the service node for the event queue, gets events that are sent to their mctl thread

The main thread of the daemon mainly handles the base class event "

①MSM_GES_RESP_V4L2:

Open: Primary initialization, foreshadowing the environment, open the thread that handles camera detail activity

Close: Perform some aftercare work

②MSM_CAM_RESP_V4L2: Handling Open and Colse

Open: Primary initialization, foreshadowing the environment, open the thread that handles camera detail activity

Close: Perform some aftercare work

③ other events are written directly to the line created by the ①② two point via pipe communication approached (send command through pipe and wait for config to return)

Important tasks in Mctl thread:

One. Open the Confing node file

Two. Call Create_camfd_receive_socket guess is a direct communication with the hardware abstraction layer

Three. Create a mctl_pp_poll_thread thread,

Four. Initialize several feature of the camera:

①zoom_init_ctrl

②bestshot_init

③hdr_init

Five. Get the control events of the server node through pipe communication, the event is obtained by the master thread of the daemon process and passed through the pipe.

Six Get the control command for the Config node by monitoring the events of the Config node

Three main types of events are monitored:

①msm_cam_resp_div_frame_evt_msg

②msm_cam_resp_mctl_pp_event

③msm_cam_resp_stat_evt_msg

The three events are sent to the PP thread created in (a) by pipe communication in the form of a command.

Important tasks in the Mctl_pp_poll_thread:

One: monitor several pipe files and interact with other threads

Several events:

①/* Events on pipe between MCTL thread-mctl pp thread */

②/* Events on user created socket */

③/* Events on mctl pp node */

④/* Events on pipe between Mctl pp thread and c2d thread */

Analysis of Qualcomm 8X camera daemon Process

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.