Android Camera 通过V4L2与kernel driver的完整交互过程

原文地址:Android Camera 通过V4L2与kernel driver的完整交互过程 作者:xinyuwuxian

Android Camera 通过V4L2与kernel driver的完整交互过程

之前在 Android Camera 的执行流程 http://blog.chinaunix.net/uid-26765074-id-3499537.html 这篇文章中已经详细介绍了
Android Camera app到调用open打开camera 设备的完成过程,但是只是到此为止,并未对较底层的操作控制等做任何分析,
今天就要进入这个环节了

这里就直接从open那个方法开始了,先说一下这个open是怎么被调用的

实例化Camera Hal接口 hardware,hardware调用initialize()进入HAL层打开Camear驱动。
CameraHardwareInterface中initialize()定义在以下路径:frameworks/base/services/camera/libcameraservice/CameraHardwareInterface.h

代码如下:

    status_t initialize(hw_module_t *module)
    {
        LOGI("Opening camera %s", mName.string());
        int rc = module->methods->open(module, mName.string(),(hw_device_t **)&mDevice);
        if (rc != OK) {
            LOGE("Could not open camera %s: %d", mName.string(), rc);
            return rc;
        }
#ifdef OMAP_ENHANCEMENT_CPCAM
        initHalPreviewWindow(&mHalPreviewWindow);
        initHalPreviewWindow(&mHalTapin);
        initHalPreviewWindow(&mHalTapout);
#else
        initHalPreviewWindow();
#endif
        return rc;
    }
此处通过module->method->open()方法真正打开Camera设备,

其中module的定义在以下路径:frameworks/base/services/camera/libcameraservice/CameraService.h

class CameraService :
    public BinderService<CameraService>,
    public BnCameraService
{

    class Client : public BnCamera
    {
    public:
        ......

    private:

        .....

    };

    camera_module_t *mModule;

};

此处还必须找到camera_module_t 的定,以更好的理解整个运行流程,通过追根溯源找到了camera_module_t 定义,

camera_module_t的定义在以下路径:hardware/libhardware/include/hardware/camera.h

typedef struct camera_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
} camera_module_t;
其中包含get_number_of_cameras方法和get_camera_info方法用于获取camera info

另外hw_module_t common;这个选项十分重要,此处应重点关注,因为是使用hw_module_t结构体中的open()方法打开设备文件的

继续找到hw_module_t 结构体的定义.在以下路径:hardware/libhardware/include/hardware/hardware.h


  1. typedef struct hw_module_t {
  2.     /** tag must be initialized to HARDWARE_MODULE_TAG */
  3.     uint32_t tag;

  4.     /** major version number for the module */
  5.     uint16_t version_major;

  6.     /** minor version number of the module */
  7.     uint16_t version_minor;

  8.     /** Identifier of module */
  9.     const char *id;

  10.     /** Name of this module */
  11.     const char *name;

  12.     /** Author/owner/implementor of the module */
  13.     const char *author;

  14.     /** Modules methods */
  15.     struct hw_module_methods_t* methods;

  16.     /** module's dso */
  17.     void* dso;

  18.     /** padding to 128 bytes, reserved for future use */
  19.     uint32_t reserved[32-7];

  20. } hw_module_t;
  1. typedef struct hw_module_methods_t {
  2.     /** Open a specific device */
  3.     int (*open)(const struct hw_module_t* module, const char* id,
  4.             struct hw_device_t** device);

  5. } hw_module_methods_t;
这里的这个open方法才是我们真正调用的open方法,那么这里只是定义,他又是在哪里实现的呢??
这个问题我们还是需要往前面追溯啊,当然这在上一篇文章中也没有提到,不卖关子了,其实重点就是我们调用了这个module->methods->open(module, mName.string(),(hw_device_t **)&mDevice)方法
但是这个module是在哪里初始化的呢?看看CameraService类里的这个方法吧,路径:frameworks/base/services/camera/libcameraservice/CameraService.cpp
  1. void CameraService::onFirstRef()
  2. {
  3.     BnCameraService::onFirstRef();

  4.     if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
  5.                 (const hw_module_t **)&mModule) < 0) {
  6.         LOGE("Could not load camera HAL module");
  7.         mNumberOfCameras = 0;
  8.     }
  9.     else {
  10.         mNumberOfCameras = mModule->get_number_of_cameras();
  11.         if (mNumberOfCameras > MAX_CAMERAS) {
  12.             LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
  13.                     mNumberOfCameras, MAX_CAMERAS);
  14.             mNumberOfCameras = MAX_CAMERAS;
  15.         }
  16.         for (int i = 0; i < mNumberOfCameras; i++) {
  17.             setCameraFree(i);
  18.         }
  19.     }
  20. }
不错,这个module正是通过这个hw_get_module方法获得的,其实他是通过方法中的CAMERA_HARDWARE_MODULE_ID作为flag最终找到已经定义好的module,那么这个已经定义好的module又在哪呢,是什么样子的呢?
这里我就直接放在这里,不在拐弯抹角了,方法路径:hardware/ti/omap4xxx/camera/CameraHal_Module.cpp
  1. static int camera_device_open(const hw_module_t* module, const char* name,
  2.                 hw_device_t** device);
  3. static int camera_device_close(hw_device_t* device);
  4. static int camera_get_number_of_cameras(void);
  5. static int camera_get_camera_info(int camera_id, struct camera_info *info);

  6. static struct hw_module_methods_t camera_module_methods = {
  7.         open: camera_device_open
  8. };

  9. camera_module_t HAL_MODULE_INFO_SYM = {
  10.     common: {
  11.          tag: HARDWARE_MODULE_TAG,
  12.          version_major: 1,
  13.          version_minor: 0,
  14.          id: CAMERA_HARDWARE_MODULE_ID,
  15.          name: "TI OMAP CameraHal Module",
  16.          author: "TI",
  17.          methods: &camera_module_methods,
  18.          dso: NULL, /* remove compilation warnings */
  19.          reserved: {0}, /* remove compilation warnings */
  20.     },
  21.     get_number_of_cameras: camera_get_number_of_cameras,
  22.     get_camera_info: camera_get_camera_info,
  23. };
这里还是很关键的,通过id:CAMERA_HARDWARE_MODULE_ID作为识别码找到这个module,get module完成任务,大家可以看到,这个定义好的module实现了methods中的open方法,
实现了camera_get_number_of_camerascamera_get_camera_info,当然还包括了其他一些变量的初始化
这里开始我们找到了我们真正需要的open方法,万里长征走完一大步了,现在就去看看这个open方法干了些什么吧
  1. /* open device handle to one of the cameras
  2.  *
  3.  * assume camera service will keep singleton of each camera
  4.  * so this function will always only be called once per camera instance
  5.  */

  6. int camera_device_open(const hw_module_t* module, const char* name,
  7.                 hw_device_t** device)
  8. {
  9.     int rv = 0;
  10.     int num_cameras = 0;
  11.     int cameraid;
  12.     ti_camera_device_t* camera_device = NULL;
  13.     camera_device_ops_t* camera_ops = NULL;
  14.     android::CameraHal* camera = NULL;
  15.     android::CameraProperties::Properties* properties = NULL;

  16.     android::Mutex::Autolock lock(gCameraHalDeviceLock);

  17.     CAMHAL_LOGI("camera_device open");

  18.     if (name != NULL) {
  19.         cameraid = atoi(name);
  20.         num_cameras = gCameraProperties.camerasSupported();

  21.         if(cameraid > num_cameras)
  22.         {
  23.             LOGE("camera service provided cameraid out of bounds, "
  24.                     "cameraid = %d, num supported = %d",
  25.                     cameraid, num_cameras);
  26.             rv = -EINVAL;
  27.             goto fail;
  28.         }

  29.         if(gCamerasOpen >= MAX_SIMUL_CAMERAS_SUPPORTED)
  30.         {
  31.             LOGE("maximum number of cameras already open");
  32.             rv = -ENOMEM;
  33.             goto fail;
  34.         }

  35.         camera_device = (ti_camera_device_t*)malloc(sizeof(*camera_device));
  36.         if(!camera_device)
  37.         {
  38.             LOGE("camera_device allocation fail");
  39.             rv = -ENOMEM;
  40.             goto fail;
  41.         }

  42.         camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
  43.         if(!camera_ops)
  44.         {
  45.             LOGE("camera_ops allocation fail");
  46.             rv = -ENOMEM;
  47.             goto fail;
  48.         }

  49.         memset(camera_device, 0, sizeof(*camera_device));
  50.         memset(camera_ops, 0, sizeof(*camera_ops));

  51.         camera_device->base.common.tag = HARDWARE_DEVICE_TAG;
  52.         camera_device->base.common.version = 0;
  53.         camera_device->base.common.module = (hw_module_t *)(module);
  54.         camera_device->base.common.close = camera_device_close;
  55.         camera_device->base.ops = camera_ops;

  56.         camera_ops->set_preview_window = camera_set_preview_window;
  57. #ifdef OMAP_ENHANCEMENT_CPCAM
  58.         camera_ops->set_buffer_source = camera_set_buffer_source;
  59. #endif
  60.         camera_ops->set_callbacks = camera_set_callbacks;
  61.         camera_ops->enable_msg_type = camera_enable_msg_type;
  62.         camera_ops->disable_msg_type = camera_disable_msg_type;
  63.         camera_ops->msg_type_enabled = camera_msg_type_enabled;
  64.         camera_ops->start_preview = camera_start_preview;
  65.         camera_ops->stop_preview = camera_stop_preview;
  66.         camera_ops->preview_enabled = camera_preview_enabled;
  67.         camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers;
  68.         camera_ops->start_recording = camera_start_recording;
  69.         camera_ops->stop_recording = camera_stop_recording;
  70.         camera_ops->recording_enabled = camera_recording_enabled;
  71.         camera_ops->release_recording_frame = camera_release_recording_frame;
  72.         camera_ops->auto_focus = camera_auto_focus;
  73.         camera_ops->cancel_auto_focus = camera_cancel_auto_focus;
  74.         camera_ops->take_picture = camera_take_picture;
  75.         camera_ops->cancel_picture = camera_cancel_picture;
  76.         camera_ops->set_parameters = camera_set_parameters;
  77.         camera_ops->get_parameters = camera_get_parameters;
  78.         camera_ops->put_parameters = camera_put_parameters;
  79.         camera_ops->send_command = camera_send_command;
  80.         camera_ops->release = camera_release;
  81.         camera_ops->dump = camera_dump;
  82. #ifdef OMAP_ENHANCEMENT_CPCAM
  83.         camera_ops->reprocess = camera_reprocess;
  84.         camera_ops->cancel_reprocess = camera_cancel_reprocess;
  85. #endif

  86.         *device = &camera_device->base.common;

  87.         // -------- TI specific stuff --------

  88.         camera_device->cameraid = cameraid;

  89.         if(gCameraProperties.getProperties(cameraid, &properties) < 0)
  90.         {
  91.             LOGE("Couldn't get camera properties");
  92.             rv = -ENOMEM;
  93.             goto fail;
  94.         }

  95.         camera = new android::CameraHal(cameraid);

  96.         if(!camera)
  97.         {
  98.             LOGE("Couldn't create instance of CameraHal class");
  99.             rv = -ENOMEM;
  100.             goto fail;
  101.         }

  102.         if(properties && (camera->initialize(properties) != android::NO_ERROR))
  103.         {
  104.             LOGE("Couldn't initialize camera instance");
  105.             rv = -ENODEV;
  106.             goto fail;
  107.         }

  108.         gCameraHals[cameraid] = camera;
  109.         gCamerasOpen++;
  110.     }

  111.     return rv;

  112. fail:
  113.     if(camera_device) {
  114.         free(camera_device);
  115.         camera_device = NULL;
  116.     }
  117.     if(camera_ops) {
  118.         free(camera_ops);
  119.         camera_ops = NULL;
  120.     }
  121.     if(camera) {
  122.         delete camera;
  123.         camera = NULL;
  124.     }
  125.     *device = NULL;
  126.     return rv;
  127. }
看看这么长的代码,open的任务还是比较中的,没办法,能者多劳嘛,红色部分是最重点的部分
从这里可以知道,这里就像一个控制中心,上传调用到这里被分发出去,实现各自的操作,我们就以startPreview为例进行分析

  1. int camera_start_preview(struct camera_device * device)
  2. {
  3.     int rv = -EINVAL;
  4.     ti_camera_device_t* ti_dev = NULL;

  5.     LOGV("%s", __FUNCTION__);

  6.     if(!device)
  7.         return rv;

  8.     ti_dev = (ti_camera_device_t*) device;

  9.     rv = gCameraHals[ti_dev->cameraid]->startPreview();

  10.     return rv;
  11. }
这里每open一个device就会相应的创建并且初始化一个CameraHal 对象,定义在:hardware/ti/omap4xxx/camera/CameraHal.cpp
并且把这个对象保存在gCameraHals这个数组中,正因为这样这里camera_start_preview才可以通过这个数据检索对象调用方法
现在我们就看看这个startPreview()方法是怎样实现的
  1. /**
  2.    @brief Start preview mode.

  3.    @param none
  4.    @return NO_ERROR Camera switched to VF mode
  5.    @todo Update function header with the different errors that are possible

  6.  */
  7. status_t CameraHal::startPreview() {
  8.     LOG_FUNCTION_NAME;

  9.     // When tunneling is enabled during VTC, startPreview happens in 2 steps:
  10.     // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION,
  11.     // cameraPreviewInitialization() is called, which in turn causes the CameraAdapter
  12.     // to move from loaded to idle state. And when the application calls startPreview,
  13.     // the CameraAdapter moves from idle to executing state.
  14.     //
  15.     // If the application calls startPreview() without sending the command
  16.     // CAMERA_CMD_PREVIEW_INITIALIZATION, then the function cameraPreviewInitialization()
  17.     // AND startPreview() are executed. In other words, if the application calls
  18.     // startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION,
  19.     // then the CameraAdapter moves from loaded to idle to executing state in one shot.
  20.     status_t ret = cameraPreviewInitialization();

  21.     // The flag mPreviewInitializationDone is set to true at the end of the function
  22.     // cameraPreviewInitialization(). Therefore, if everything goes alright, then the
  23.     // flag will be set. Sometimes, the function cameraPreviewInitialization() may
  24.     // return prematurely if all the resources are not available for starting preview.
  25.     // For example, if the preview window is not set, then it would return NO_ERROR.
  26.     // Under such circumstances, one should return from startPreview as well and should
  27.     // not continue execution. That is why, we check the flag and not the return value.
  28.     if (!mPreviewInitializationDone) return ret;

  29.     // Once startPreview is called, there is no need to continue to remember whether
  30.     // the function cameraPreviewInitialization() was called earlier or not. And so
  31.     // the flag mPreviewInitializationDone is reset here. Plus, this preserves the
  32.     // current behavior of startPreview under the circumstances where the application
  33.     // calls startPreview twice or more.
  34.     mPreviewInitializationDone = false;

  35.     ///Enable the display adapter if present, actual overlay enable happens when we post the buffer
  36.     if(mDisplayAdapter.get() != NULL) {
  37.         CAMHAL_LOGDA("Enabling display");
  38.         int width, height;
  39.         mParameters.getPreviewSize(&width, &height);

  40. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
  41.         ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview);
  42. #else
  43.         ret = mDisplayAdapter->enableDisplay(width, height, NULL);
  44. #endif

  45.         if ( ret != NO_ERROR ) {
  46.             CAMHAL_LOGEA("Couldn't enable display");

  47.             // FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called
  48.             // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW)
  49.             // below. But this will never happen because of goto error. Thus at next
  50.             // startPreview() call CameraHAL will be deadlocked.
  51.             // Need to revisit mStateSwitch lock, for now just abort the process.
  52.             CAMHAL_ASSERT_X(false,
  53.                 "At this stage mCameraAdapter->mStateSwitchLock is still locked, "
  54.                 "deadlock is guaranteed");

  55.             goto error;
  56.         }

  57.     }

  58.     ///Send START_PREVIEW command to adapter
  59.     CAMHAL_LOGDA("Starting CameraAdapter preview mode");

  60.     ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW);

  61.     if(ret!=NO_ERROR) {
  62.         CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter");
  63.         goto error;
  64.     }
  65.     CAMHAL_LOGDA("Started preview");

  66.     mPreviewEnabled = true;
  67.     mPreviewStartInProgress = false;
  68.     return ret;

  69.     error:

  70.         CAMHAL_LOGEA("Performing cleanup after error");

  71.         //Do all the cleanup
  72.         freePreviewBufs();
  73.         mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
  74.         if(mDisplayAdapter.get() != NULL) {
  75.             mDisplayAdapter->disableDisplay(false);
  76.         }
  77.         mAppCallbackNotifier->stop();
  78.         mPreviewStartInProgress = false;
  79.         mPreviewEnabled = false;
  80.         LOG_FUNCTION_NAME_EXIT;

  81.         return ret;
  82. }
在我的理解看来上面标注的部分是这个方法的关键,这个地方可是会让初次研究这里的人晕头转向的,因为我就在这里犯了错误,走岔道了,下面会说明到底是怎么走岔道的
先说一下吧,这里调用mCameraAdapter对象的sendCommand方法

  1. status_t BaseCameraAdapter::sendCommand(CameraCommands operation, int value1, int value2, int value3, int value4) {
  2.     status_t ret = NO_ERROR;
  3.     struct timeval *refTimestamp;
  4.     BuffersDescriptor *desc = NULL;
  5.     CameraFrame *frame = NULL;

  6.     LOG_FUNCTION_NAME;

  7.     switch ( operation ) {
  8.         case:
  9.             ...............
  10.         case CameraAdapter::CAMERA_START_PREVIEW:
            {
                CAMHAL_LOGDA("Start Preview");
                if ( ret == NO_ERROR )
                {
                    ret = setState(operation);
                }

                if ( ret == NO_ERROR )
                {
                    ret = startPreview();
                }

                if ( ret == NO_ERROR )
                {
                    ret = commitState();
                }else{
                    ret |= rollbackState();
                }
                break;
            }
  11.     }
  12. }
  1. status_t BaseCameraAdapter::setState(CameraCommands operation)
  2. {
  3.     status_t ret = NO_ERROR;

  4.     LOG_FUNCTION_NAME;

  5.     const char *printState = getLUTvalue_translateHAL(operation, CamCommandsLUT);

  6.     mLock.lock();

  7.     switch ( mAdapterState )
  8.         {

  9.         case INTIALIZED_STATE:
  10.             ............

  11.         case LOADED_PREVIEW_STATE:

  12.             switch ( operation )
  13.                 {

  14.                 case CAMERA_START_PREVIEW:
  15.                     CAMHAL_LOGDB("Adapter state switch LOADED_PREVIEW_STATE->PREVIEW_STATE event = %s",
  16.                             printState);
  17.                     mNextState = PREVIEW_STATE;
  18.                     break;
  19.                 }
  20.         }
  21. }
  1. status_t BaseCameraAdapter::startPreview()
  2. {
  3.     status_t ret = NO_ERROR;

  4.     LOG_FUNCTION_NAME;

  5.     LOG_FUNCTION_NAME_EXIT;

  6.     return ret;
  7. }
就是这里了,所以我用可很醒目的颜色标注出来,很多人会想当然的理解,你不是调用了startPreview方法嘛,那就是他了啊!可是这里为什么什么动作都没做呢??
于是就卡在这里不知所措了,那个纠结啊
现在就来解开这个谜团吧!!!

这个我们还是要往前追溯了,追溯到哪里呢??那就从这里开始吧
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW);
这个方式是在CameraHalstartPreview() 方法中被调用的
所以我要知道这个mCameraAdapter对象原型是什么啊,他从哪里而来,原来他是CameraHal这个类的一个成员,定义在:hardware/ti/omap4xxx/camera/inc/CameraHal.h
CameraAdapter *mCameraAdapter;
这里必须打破砂锅追到底,找到CameraAdapter 这个类的定义,他的定义同样这这个.h文件中

  1. /**
  2.   * CameraAdapter interface class
  3.   * Concrete classes derive from this class and provide implementations based on the specific camera h/w interface
  4.   */

  5. class CameraAdapter: public FrameNotifier, public virtual RefBase
  6. {
  7. protected:
  8.     enum AdapterActiveStates {
  9.         INTIALIZED_ACTIVE = 1 << 0,
  10.         LOADED_PREVIEW_ACTIVE = 1 << 1,
  11.         PREVIEW_ACTIVE = 1 << 2,
  12.         LOADED_CAPTURE_ACTIVE = 1 << 3,
  13.         CAPTURE_ACTIVE = 1 << 4,
  14.         BRACKETING_ACTIVE = 1 << 5,
  15.         AF_ACTIVE = 1 << 6,
  16.         ZOOM_ACTIVE = 1 << 7,
  17.         VIDEO_ACTIVE = 1 << 8,
  18.         LOADED_REPROCESS_ACTIVE = 1 << 9,
  19.         REPROCESS_ACTIVE = 1 << 10,
  20.     };
  21. public:
  22.     typedef struct
  23.         {
  24.          CameraBuffer *mBuffers;
  25.          uint32_t *mOffsets;
  26.          int mFd;
  27.          size_t mLength;
  28.          size_t mCount;
  29.          size_t mMaxQueueable;
  30.         } BuffersDescriptor;

  31.     enum CameraCommands
  32.         {
  33.         CAMERA_START_PREVIEW = 0,
  34.         CAMERA_STOP_PREVIEW = 1,
  35.         CAMERA_START_VIDEO = 2,
  36.         CAMERA_STOP_VIDEO = 3,
  37.         CAMERA_START_IMAGE_CAPTURE = 4,
  38.         CAMERA_STOP_IMAGE_CAPTURE = 5,
  39.         CAMERA_PERFORM_AUTOFOCUS = 6,
  40.         CAMERA_CANCEL_AUTOFOCUS = 7,
  41.         CAMERA_PREVIEW_FLUSH_BUFFERS = 8,
  42.         CAMERA_START_SMOOTH_ZOOM = 9,
  43.         CAMERA_STOP_SMOOTH_ZOOM = 10,
  44.         CAMERA_USE_BUFFERS_PREVIEW = 11,
  45.         CAMERA_SET_TIMEOUT = 12,
  46.         CAMERA_CANCEL_TIMEOUT = 13,
  47.         CAMERA_START_BRACKET_CAPTURE = 14,
  48.         CAMERA_STOP_BRACKET_CAPTURE = 15,
  49.         CAMERA_QUERY_RESOLUTION_PREVIEW = 16,
  50.         CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE = 17,
  51.         CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA = 18,
  52.         CAMERA_USE_BUFFERS_IMAGE_CAPTURE = 19,
  53.         CAMERA_USE_BUFFERS_PREVIEW_DATA = 20,
  54.         CAMERA_TIMEOUT_EXPIRED = 21,
  55.         CAMERA_START_FD = 22,
  56.         CAMERA_STOP_FD = 23,
  57.         CAMERA_SWITCH_TO_EXECUTING = 24,
  58.         CAMERA_USE_BUFFERS_VIDEO_CAPTURE = 25,
  59. #ifdef OMAP_ENHANCEMENT_CPCAM
  60.         CAMERA_USE_BUFFERS_REPROCESS = 26,
  61.         CAMERA_START_REPROCESS = 27,
  62. #endif
  63. #ifdef OMAP_ENHANCEMENT_VTC
  64.         CAMERA_SETUP_TUNNEL = 28,
  65.         CAMERA_DESTROY_TUNNEL = 29,
  66. #endif
  67.         CAMERA_PREVIEW_INITIALIZATION = 30,
  68.         };

  69.     enum CameraMode
  70.         {
  71.         CAMERA_PREVIEW,
  72.         CAMERA_IMAGE_CAPTURE,
  73.         CAMERA_VIDEO,
  74.         CAMERA_MEASUREMENT,
  75.         CAMERA_REPROCESS,
  76.         };

  77.     enum AdapterState {
  78.         INTIALIZED_STATE = INTIALIZED_ACTIVE,
  79.         LOADED_PREVIEW_STATE = LOADED_PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  80.         PREVIEW_STATE = PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  81.         LOADED_CAPTURE_STATE = LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  82.         CAPTURE_STATE = CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  83.         BRACKETING_STATE = BRACKETING_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE ,
  84.         AF_STATE = AF_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  85.         ZOOM_STATE = ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  86.         VIDEO_STATE = VIDEO_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  87.         VIDEO_AF_STATE = VIDEO_ACTIVE | AF_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  88.         VIDEO_ZOOM_STATE = VIDEO_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  89.         VIDEO_LOADED_CAPTURE_STATE = VIDEO_ACTIVE | LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  90.         VIDEO_CAPTURE_STATE = VIDEO_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  91.         AF_ZOOM_STATE = AF_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  92.         BRACKETING_ZOOM_STATE = BRACKETING_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  93.         LOADED_REPROCESS_STATE = LOADED_REPROCESS_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  94.         LOADED_REPROCESS_CAPTURE_STATE = LOADED_REPROCESS_ACTIVE | LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  95.         REPROCESS_STATE = REPROCESS_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
  96.     };


  97. public:

  98.     ///Initialzes the camera adapter creates any resources required
  99.     virtual int initialize(CameraProperties::Properties*) = 0;

  100.     virtual int setErrorHandler(ErrorNotifier *errorNotifier) = 0;

  101.     //Message/Frame notification APIs
  102.     virtual void enableMsgType(int32_t msgs,
  103.                                frame_callback callback = NULL,
  104.                                event_callback eventCb = NULL,
  105.                                void *cookie = NULL) = 0;
  106.     virtual void disableMsgType(int32_t msgs, void* cookie) = 0;
  107.     virtual void returnFrame(CameraBuffer* frameBuf, CameraFrame::FrameType frameType) = 0;
  108.     virtual void addFramePointers(CameraBuffer *frameBuf, void *buf) = 0;
  109.     virtual void removeFramePointers() = 0;

  110.     //APIs to configure Camera adapter and get the current parameter set
  111.     virtual int setParameters(const CameraParameters& params) = 0;
  112.     virtual void getParameters(CameraParameters& params) = 0;

  113.     //Registers callback for returning image buffers back to CameraHAL
  114.     virtual int registerImageReleaseCallback(release_image_buffers_callback callback, void *user_data) = 0;

  115.     //Registers callback, which signals a completed image capture
  116.     virtual int registerEndCaptureCallback(end_image_capture_callback callback, void *user_data) = 0;

  117.     //API to send a command to the camera
  118.     virtual status_t sendCommand(CameraCommands operation, int value1=0, int value2=0, int value3=0, int value4=0) = 0;

  119.     virtual ~CameraAdapter() {};

  120.     //Retrieves the current Adapter state
  121.     virtual AdapterState getState() = 0;

  122.     //Retrieves the next Adapter state
  123.     virtual AdapterState getNextState() = 0;

  124.     // Receive orientation events from CameraHal
  125.     virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt) = 0;

  126.     // Rolls the state machine back to INTIALIZED_STATE from the current state
  127.     virtual status_t rollbackToInitializedState() = 0;

  128.     // Retrieves the current Adapter state - for internal use (not locked)
  129.     virtual status_t getState(AdapterState &state) = 0;
  130.     // Retrieves the next Adapter state - for internal use (not locked)
  131.     virtual status_t getNextState(AdapterState &state) = 0;

  132. protected:
  133.     //The first two methods will try to switch the adapter state.
  134.     //Every call to setState() should be followed by a corresponding
  135.     //call to commitState(). If the state switch fails, then it will
  136.     //get reset to the previous state via rollbackState().
  137.     virtual status_t setState(CameraCommands operation) = 0;
  138.     virtual status_t commitState() = 0;
  139.     virtual status_t rollbackState() = 0;
  140. };
看一下我标出的这是红色部分啊,为什么我要把它们标注成红色呢??
懂C++面向对象思想应该都知道virtual这个关键字是干什么的,
如果一个类的方法被定义为virtual如果该类的子类实现了同样的方法,则这个方法被调用的时候,会忽略父类的实现,而直接调用子类的实现,前提是方法名,包括变量类型,个数必须一致
那么这里有没有类继承了CameraAdapter 这个类,并且实现了其中的一些虚拟函数呢??答案是肯定的,我可是吃了苦头才发现的
不过也是赖自己,这是只有定义是没有实现的,肯定是由子类来实现这是方法的,不,还是不赖自己,让我吃苦头的是这里是双层继承的,双层继承啊,我怎么知道
不卖关子了,那么谁继承了
CameraAdapter 这个类呢? 先给路径:hardware/ti/omap4xxx/camera/inc/BaseCameraAdapter.h

  1. class BaseCameraAdapter : public CameraAdapter
  2. {

  3. public:

  4.     BaseCameraAdapter();
  5.     virtual ~BaseCameraAdapter();

  6.     ///Initialzes the camera adapter creates any resources required
  7.     virtual status_t initialize(CameraProperties::Properties*) = 0;

  8.     virtual int setErrorHandler(ErrorNotifier *errorNotifier);

  9.     //Message/Frame notification APIs
  10.     virtual void enableMsgType(int32_t msgs, frame_callback callback=NULL, event_callback eventCb=NULL, void* cookie=NULL);
  11.     virtual void disableMsgType(int32_t msgs, void* cookie);
  12.     virtual void returnFrame(CameraBuffer * frameBuf, CameraFrame::FrameType frameType);
  13.     virtual void addFramePointers(CameraBuffer *frameBuf, void *y_uv);
  14.     virtual void removeFramePointers();

  15.     //APIs to configure Camera adapter and get the current parameter set
  16.     virtual status_t setParameters(const CameraParameters& params) = 0;
  17.     virtual void getParameters(CameraParameters& params) = 0;

  18.     //API to send a command to the camera
  19.     virtual status_t sendCommand(CameraCommands operation, int value1 = 0, int value2 = 0, int value3 = 0, int value4 = 0 );

  20.     virtual status_t registerImageReleaseCallback(release_image_buffers_callback callback, void *user_data);

  21.     virtual status_t registerEndCaptureCallback(end_image_capture_callback callback, void *user_data);

  22.     //Retrieves the current Adapter state
  23.     virtual AdapterState getState();
  24.     //Retrieves the next Adapter state
  25.     virtual AdapterState getNextState();

  26.     // Rolls the state machine back to INTIALIZED_STATE from the current state
  27.     virtual status_t rollbackToInitializedState();

  28. protected:
  29.     //The first two methods will try to switch the adapter state.
  30.     //Every call to setState() should be followed by a corresponding
  31.     //call to commitState(). If the state switch fails, then it will
  32.     //get reset to the previous state via rollbackState().
  33.     virtual status_t setState(CameraCommands operation);
  34.     virtual status_t commitState();
  35.     virtual status_t rollbackState();

  36.     // Retrieves the current Adapter state - for internal use (not locked)
  37.     virtual status_t getState(AdapterState &state);
  38.     // Retrieves the next Adapter state - for internal use (not locked)
  39.     virtual status_t getNextState(AdapterState &state);

  40.     //-----------Interface that needs to be implemented by deriving classes --------------------

  41.     //Should be implmented by deriving classes in order to start image capture
  42.     virtual status_t takePicture();

  43.     //Should be implmented by deriving classes in order to start image capture
  44.     virtual status_t stopImageCapture();

  45.     //Should be implmented by deriving classes in order to start temporal bracketing
  46.     virtual status_t startBracketing(int range);

  47.     //Should be implemented by deriving classes in order to stop temporal bracketing
  48.     virtual status_t stopBracketing();

  49.     //Should be implemented by deriving classes in oder to initiate autoFocus
  50.     virtual status_t autoFocus();

  51.     //Should be implemented by deriving classes in oder to initiate autoFocus
  52.     virtual status_t cancelAutoFocus();

  53.     //Should be called by deriving classes in order to do some bookkeeping
  54.     virtual status_t startVideoCapture();

  55.     //Should be called by deriving classes in order to do some bookkeeping
  56.     virtual status_t stopVideoCapture();

  57.     //Should be implemented by deriving classes in order to start camera preview
  58.     virtual status_t startPreview();

  59.     //Should be implemented by deriving classes in order to stop camera preview
  60.     virtual status_t stopPreview();

  61.     //Should be implemented by deriving classes in order to start smooth zoom
  62.     virtual status_t startSmoothZoom(int targetIdx);

  63.     //Should be implemented by deriving classes in order to stop smooth zoom
  64.     virtual status_t stopSmoothZoom();

  65.     //Should be implemented by deriving classes in order to stop smooth zoom
  66.     virtual status_t useBuffers(CameraMode mode, CameraBuffer* bufArr, int num, size_t length, unsigned int queueable);

  67.     //Should be implemented by deriving classes in order queue a released buffer in CameraAdapter
  68.     virtual status_t fillThisBuffer(CameraBuffer* frameBuf, CameraFrame::FrameType frameType);

  69.     //API to get the frame size required to be allocated. This size is used to override the size passed
  70.     //by camera service when VSTAB/VNF is turned ON for example
  71.     virtual status_t getFrameSize(size_t &width, size_t &height);

  72.     //API to get required data frame size
  73.     virtual status_t getFrameDataSize(size_t &dataFrameSize, size_t bufferCount);

  74.     //API to get required picture buffers size with the current configuration in CameraParameters
  75.     virtual status_t getPictureBufferSize(size_t &length, size_t bufferCount);

  76.     // Should be implemented by deriving classes in order to start face detection
  77.     // ( if supported )
  78.     virtual status_t startFaceDetection();

  79.     // Should be implemented by deriving classes in order to stop face detection
  80.     // ( if supported )
  81.     virtual status_t stopFaceDetection();

  82.     virtual status_t switchToExecuting();

  83.     virtual status_t setupTunnel(uint32_t SliceHeight, uint32_t EncoderHandle, uint32_t width, uint32_t height);

  84.     virtual status_t destroyTunnel();

  85.     virtual status_t cameraPreviewInitialization();

  86.     // Receive orientation events from CameraHal
  87.     virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);

  88.     // ---------------------Interface ends-----------------------------------

  89.     status_t notifyFocusSubscribers(CameraHalEvent::FocusStatus status);
  90.     status_t notifyShutterSubscribers();
  91.     status_t notifyZoomSubscribers(int zoomIdx, bool targetReached);
  92.     status_t notifyMetadataSubscribers(sp<CameraMetadataResult> &meta);

  93.     //Send the frame to subscribers
  94.     status_t sendFrameToSubscribers(CameraFrame *frame);

  95.     //Resets the refCount for this particular frame
  96.     status_t resetFrameRefCount(CameraFrame &frame);

  97.     //A couple of helper functions
  98.     void setFrameRefCount(CameraBuffer* frameBuf, CameraFrame::FrameType frameType, int refCount);
  99.     int getFrameRefCount(CameraBuffer* frameBuf, CameraFrame::FrameType frameType);
  100.     int setInitFrameRefCount(CameraBuffer* buf, unsigned int mask);
  101.     static const char* getLUTvalue_translateHAL(int Value, LUTtypeHAL LUT);

  102.     .................
  103.     .................
  104. }
这里我只列出了一部分代码,不过大家清楚了,BaseCameraAdapter 继承CameraAdapter,不过这里还没完呢,看看这个类中定义的方法
那么多的virtual 方法,后来自己才发现的,他还是被别的类继承了,而且其中的很多方法被子类重新实现了
所以实现上上面调用的startPreview方法其实不是BaseCameraAdapter.cpp中实现的那个startPreview方法
那挺调用的startPreview方法在哪里呢,自然是继承了BaseCameraAdapter 类的那个子类实现的startPreview
现在就把这个罪魁祸首拉上来,先看定义:hardware/ti/omap4xxx/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h


  1. /**
  2.   * Class which completely abstracts the camera hardware interaction from camera hal
  3.   * TODO: Need to list down here, all the message types that will be supported by this class
  4.                 Need to implement BufferProvider interface to use AllocateBuffer of OMX if needed
  5.   */
  6. class V4LCameraAdapter : public BaseCameraAdapter
  7. {
  8. public:

  9.     /*--------------------Constant declarations----------------------------------------*/
  10.     static const int32_t MAX_NO_BUFFERS = 20;

  11.     ///@remarks OMX Camera has six ports - buffer input, time input, preview, image, video, and meta data
  12.     static const int MAX_NO_PORTS = 6;

  13.     ///Five second timeout
  14.     static const int CAMERA_ADAPTER_TIMEOUT = 5000*1000;

  15. public:

  16.     V4LCameraAdapter(size_t sensor_index);
  17.     ~V4LCameraAdapter();


  18.     ///Initialzes the camera adapter creates any resources required
  19.     virtual status_t initialize(CameraProperties::Properties*);

  20.     //APIs to configure Camera adapter and get the current parameter set
  21.     virtual status_t setParameters(const CameraParameters& params);
  22.     virtual void getParameters(CameraParameters& params);

  23.     // API
  24.     virtual status_t UseBuffersPreview(CameraBuffer *bufArr, int num);
  25.     virtual status_t UseBuffersCapture(CameraBuffer *bufArr, int num);

  26.     static status_t getCaps(const int sensorId, CameraProperties::Properties* params, V4L_HANDLETYPE handle);

  27. protected:

  28. //----------Parent class method implementation------------------------------------//看看人家这里说的很清楚,这是父类的方法
  29.     virtual status_t startPreview();
  30.     virtual status_t stopPreview();
  31.     virtual status_t takePicture();
  32.     virtual status_t stopImageCapture();
  33.     virtual status_t autoFocus();
  34.     virtual status_t useBuffers(CameraMode mode, CameraBuffer *bufArr, int num, size_t length, unsigned int queueable);
  35.     virtual status_t fillThisBuffer(CameraBuffer *frameBuf, CameraFrame::FrameType frameType);
  36.     virtual status_t getFrameSize(size_t &width, size_t &height);
  37.     virtual status_t getPictureBufferSize(size_t &length, size_t bufferCount);
  38.     virtual status_t getFrameDataSize(size_t &dataFrameSize, size_t bufferCount);
  39.     virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);
  40. //-----------------------------------------------------------------------------


  41. private:

  42.     class PreviewThread : public Thread {
  43.             V4LCameraAdapter* mAdapter;
  44.         public:
  45.             PreviewThread(V4LCameraAdapter* hw) :
  46.                     Thread(false), mAdapter(hw) { }
  47.             virtual void onFirstRef() {
  48.                 run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
  49.             }
  50.             virtual bool threadLoop() {
  51.                 mAdapter->previewThread();
  52.                 // loop until we need to quit
  53.                 return true;
  54.             }
  55.         };

  56.     //Used for calculation of the average frame rate during preview
  57.     status_t recalculateFPS();

  58.     char * GetFrame(int &index);

  59.     int previewThread();

  60. public:

  61. private:
  62.     //capabilities data
  63.     static const CapPixelformat mPixelformats [];
  64.     static const CapResolution mPreviewRes [];
  65.     static const CapFramerate mFramerates [];
  66.     static const CapResolution mImageCapRes [];

  67.     //camera defaults
  68.     static const char DEFAULT_PREVIEW_FORMAT[];
  69.     static const char DEFAULT_PREVIEW_SIZE[];
  70.     static const char DEFAULT_FRAMERATE[];
  71.     static const char DEFAULT_NUM_PREV_BUFS[];

  72.     static const char DEFAULT_PICTURE_FORMAT[];
  73.     static const char DEFAULT_PICTURE_SIZE[];
  74.     static const char DEFAULT_FOCUS_MODE[];
  75.     static const char * DEFAULT_VSTAB;
  76.     static const char * DEFAULT_VNF;

  77.     static status_t insertDefaults(CameraProperties::Properties*, V4L_TI_CAPTYPE&);
  78.     static status_t insertCapabilities(CameraProperties::Properties*, V4L_TI_CAPTYPE&);
  79.     static status_t insertPreviewFormats(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
  80.     static status_t insertPreviewSizes(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
  81.     static status_t insertImageSizes(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
  82.     static status_t insertFrameRates(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
  83.     static status_t sortAscend(V4L_TI_CAPTYPE&, uint16_t ) ;

  84.     status_t v4lIoctl(int, int, void*);
  85.     status_t v4lInitMmap(int&);
  86.     status_t v4lInitUsrPtr(int&);
  87.     status_t v4lStartStreaming();
  88.     status_t v4lStopStreaming(int nBufferCount);
  89.     status_t v4lSetFormat(int, int, uint32_t);
  90.     status_t restartPreview();


  91.     int mPreviewBufferCount;
  92.     int mPreviewBufferCountQueueable;
  93.     int mCaptureBufferCount;
  94.     int mCaptureBufferCountQueueable;
  95.     KeyedVector<CameraBuffer *, int> mPreviewBufs;
  96.     KeyedVector<CameraBuffer *, int> mCaptureBufs;
  97.     mutable Mutex mPreviewBufsLock;
  98.     mutable Mutex mCaptureBufsLock;
  99.     mutable Mutex mStopPreviewLock;

  100.     CameraParameters mParams;

  101.     bool mPreviewing;
  102.     bool mCapturing;
  103.     Mutex mLock;

  104.     int mFrameCount;
  105.     int mLastFrameCount;
  106.     unsigned int mIter;
  107.     nsecs_t mLastFPSTime;

  108.     //variables holding the estimated framerate
  109.     float mFPS, mLastFPS;

  110.     int mSensorIndex;

  111.     // protected by mLoc
大家看到了V4LCameraAdapter 又继承了BaseCameraAdapter,双层继承,实现了父类的一些方法
所有这里算是媳妇熬着婆了,终于找到了我们想要的startPreview
不过看到终于进入了V4LCameraAdapter 这个类,我知道,离成功已经很近了,V4L2就是直接去和driver谈判的
那么我们就看看
V4LCameraAdapter 这个类中的startPreview方法吧,路径:ardware/ti/omap4xxx/camera/V4LCameraAdapter/V4LCameraAdapter.cpp

  1. status_t V4LCameraAdapter::startPreview()
  2. {
  3.     status_t ret = NO_ERROR;

  4.     LOG_FUNCTION_NAME;
  5.     Mutex::Autolock lock(mPreviewBufsLock);

  6.     if(mPreviewing) {
  7.         ret = BAD_VALUE;
  8.         goto EXIT;
  9.     }

  10.     for (int i = 0; i < mPreviewBufferCountQueueable; i++) {

  11.         mVideoInfo->buf.index = i;
  12.         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  13.         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;

  14.         ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
  15.         if (ret < 0) {
  16.             CAMHAL_LOGEA("VIDIOC_QBUF Failed");
  17.             goto EXIT;
  18.         }
  19.         nQueued++;
  20.     }

  21.     ret = v4lStartStreaming();

  22.     // Create and start preview thread for receiving buffers from V4L Camera
  23.     if(!mCapturing) {
  24.         mPreviewThread = new PreviewThread(this);
  25.         CAMHAL_LOGDA("Created preview thread");
  26.     }
不错,这条语句就是我一直找寻的,真是众里寻他千百度,蓦然回首,那句就在灯火阑珊处
这样,其他的事情就全部由v4l2去做了,这些过程会单独分一章去学习
还有就是上面绿的部分,同样要分一章学习,很重要

待续。。。。。。。。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469417.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Pytorch神经网络理论篇】 05 Module类的使用方法+参数Parameters类+定义训练模型的步骤与方法

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

BZOJ 2822: [AHOI2012]树屋阶梯 [Catalan数 高精度]

2822: [AHOI2012]树屋阶梯 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 779 Solved: 453[Submit][Status][Discuss]Description 暑假期间&#xff0c;小龙报名了一个模拟野外生存作战训练班来锻炼体魄&#xff0c;训练的第一个晚上&#xff0c;教官就给他们出了个难题。由…

【Pytorch神经网络理论篇】 06 神经元+神经网络模型+全连接网络模型

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

面试题:N皇后问题,思路和python解题笔记

n皇后问题算法思路和python解法 问题描述 n皇后问题&#xff0c;在nn的棋盘上&#xff0c;解出n个皇后所有不能互相攻击的摆法&#xff0c; 皇后在数组中用“Q”表示&#xff0c;空地用“.”表示 返回的数据结构格式要求&#xff1a;[[“.Q…”,“…Q”,“Q…”,“…Q.”],[“…

【Pytorch神经网络理论篇】 07 激活函数+Sigmoid+tanh+ReLU+Swish+Mish+GELU

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

【Pytorch神经网络理论篇】 08 Softmax函数(处理分类问题)

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

Python套接字编程Socket Progaming——1

本篇文章是Network And Web Programing-Socket Programing分类中的第一篇文章&#xff0c;内容主要包含 Socket概念理解Socket programing介绍一个简单的TCP协议的server-client程序支持同时处理多个客户端简单server-client连接程序socket的常用选项使用 理解socket概念 一…

【Pytorch神经网络理论篇】 09 神经网络模块中的损失函数

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

【Pytorch神经网络理论篇】 10 优化器模块+退化学习率

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

HAProxy负载均衡原理及企业级实例部署haproxy集群

HAProxy是一种高效、可靠、免费的高可用及负载均衡解决方案&#xff0c;非常适合于高负载站点的七层数据请求。客户端通过HAProxy代理服务器获得站点页面&#xff0c;而代理服务器收到客户请求后根据负载均衡的规则将请求数据转发给后端真实服务器。 同一客户端访问服务器&…

【Pytorch神经网络实战案例】07 预测泰坦尼克号上生存的乘客

1 样本处理 1.1 载入样本代码---Titanic forecast.py&#xff08;第1部分&#xff09; import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from scipy import stats import pandas as pd import matplotlib.pyplot as plt import os o…

基于sanic的服务使用celery完成动态修改定时任务

首先声明一下 考虑到celery目前和asyncio的不兼容性&#xff0c;协程任务需要转换为非异步的普通方法才能被当做task加入定时&#xff0c;并且celery和asyncio使用可能会带来预想不到的问题&#xff0c;在celery官方第二次承诺的6.0版本融合asyncio之前&#xff0c;需要慎重考虑…

Pyscript,使用Python编写前端脚本

介绍 Anaconda的CEO Peter Wang在前两个月的时候发布了Pyscript&#xff0c;实现了在HTML支持Python的使用&#xff0c;整个引用过程甚至不需要安装任何环境&#xff0c;只需要使用link和script标签即可引用实现Python在HTML中运行的功能&#xff0c;在HTML中也可以运行和使用…

如何把应用程序app编译进android系统

转载&#xff1a;http://ywxiao66.blog.163.com/blog/static/175482055201152710441106/------------------------------------------------------------------把常用的应用程序编译到img文件中&#xff0c;就成了系统的一部分&#xff0c;用户不必自己安装&#xff0c;当然也卸…

【Pytorch神经网络实战案例】08 识别黑白图中的服装图案(Fashion-MNIST)

1 Fashion-MNIST简介 FashionMNIST 是一个替代 MNIST 手写数字集 的图像数据集。 它是由 Zalando&#xff08;一家德国的时尚科技公司&#xff09;旗下的研究部门提供。其涵盖了来自 10 种类别的共 7 万个不同商品的正面图片。 FashionMNIST 的大小、格式和训练集/测试集划分与…

PHP list的赋值

List右边的赋值对象是一个以数值为索引的数组&#xff0c;左边的变量的位置和赋值对象的键值一一对应&#xff0c;有些位置的变量可以省略不写。非末尾的被赋值变量省略时&#xff0c;分隔的逗号不能省略。左边变量被赋值的顺序是从右到左的。 1 list($a, ,$b,$c[],$c[]) [1,2…

Pyscript,创建一个能执行crud操作的网页应用

目录 实现一个添加邀请客人名单的功能 循序渐进&#xff0c;逐步实现&#xff1a; 输入客人名称&#xff0c;按下enter键添加客人名单点击客人名单在名单上添加或者取消添加删除线&#xff0c;表示已经检查客人到场或未到场 checkbox&#xff0c;点击客人名单或者点击checkb…

爬虫实战学习笔记_1 爬虫基础+HTTP原理

1 爬虫简介 网络爬虫&#xff08;又被称作网络蜘蛛、网络机器人&#xff0c;在某些社区中也经常被称为网页追逐者)可以按照指定的规则&#xff08;网络爬虫的算法&#xff09;自动浏览或抓取网络中的信息。 1.1 Web网页存在方式 表层网页指的是不需要提交表单&#xff0c;使…

爬虫实战学习笔记_2 网络请求urllib模块+设置请求头+Cookie+模拟登陆

1 urllib模块 1.1 urllib模块简介 Python3中将urib与urllib2模块的功能组合&#xff0c;并且命名为urllib。Python3中的urllib模块中包含多个功能的子模块&#xff0c;具体内容如下。 urllib.request&#xff1a;用于实现基本HTTP请求的模块。urlb.error&#xff1a;异常处理…

java----IO和NIO的区别

概念&#xff1a;NIO即New IO&#xff0c;这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的&#xff0c;但实现方式不同&#xff0c;NIO主要用到的是块&#xff0c;所以NIO的效率要比IO高很多。在Java API中提供了两套NIO&#xff0c;一套是针对标准输入输出NIO&#xf…