【華爲Hicar倒車影像分流需求 六】- 共享內存方案最終代碼實現 一 之 數據接收端

本文接着《【華爲Hicar倒車影像分流需求 五】- 共享內存方案最終代碼實現 一 之 數據發送端

二、共享內存接收端代碼實現

1. 頭文件 H264_Reverse.h

# nativecamerasdk/video/H264_Reverse.h
#ifndef __H264_REVERSE_H__  
#define __H264_REVERSE_H__

#define DLS_CAMERA_PREVIEW_WIDTH 	720  	//raw camera output
#define DLS_CAMERA_PREVIEW_HEIGHT	480 	//raw camera output

//YUV420-N21      YYYYYYYY UVUV
#define MAX_BUF_SIZE 	DLS_CAMERA_PREVIEW_WIDTH * DLS_CAMERA_PREVIEW_HEIGHT * 3/2 + 200

#define  REVERSE_CAMERA_DUMP_LOCATION  "/sdcard/reverse/"


// 進程鎖結構體
typedef struct MUTEX_SHAREDLOCK {
    pthread_mutex_t lock;
    pthread_mutexattr_t lock_attr;
} mutex_sharedLock_t;


class Camera_Shared_Memory_R
{
public:
	static Camera_Shared_Memory_R* get_Read_Shared_Memory();

	int attach_Read_Shared_Memory();

	int open_Read_Shared_Memory(unsigned char *buffer);

	int close_Read_Shared_Memory();

	int shm_chn_attach();
			
	unsigned char * shm_addr_buff;	

	// dump data
	void Camera_Shared_Memory_Dump(unsigned char * buf, int size);

private:
	//method declare  	
	Camera_Shared_Memory_R();
	~Camera_Shared_Memory_R();
	static Camera_Shared_Memory_R* sInstance;	

	void* shm_addr;	
	int shm_id;
	
};

#endif   // END __H264_REVERSE_H__

2. 源文件 H264_Reverse.cpp

# nativecamerasdk/video/H264_Reverse.cpp

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <sys/stat.h>

#include "H264_Reverse.h"

static mutex_sharedLock_t *sharedLock_r;
Camera_Shared_Memory_R* Camera_Shared_Memory_R::sInstance = 0;

Camera_Shared_Memory_R::Camera_Shared_Memory_R():shm_addr(NULL),shm_id(0)
{
    attach_Read_Shared_Memory(); 
    // alloc buffer
    shm_addr_buff = (unsigned char *)malloc(MAX_BUF_SIZE);
}

Camera_Shared_Memory_R::~Camera_Shared_Memory_R()
{
    // release addr
    close_Read_Shared_Memory();
   
    // who create who destroy, so don't delete IPC memory here
    //if(shmctl(shm_id, IPC_RMID, NULL) !=0 )
    //    ALOGI("[%s][%d] shmctl error!,shm_id=%d \n",  __func__,__LINE__, shm_id);
    
    // free buffer
    free(shm_addr_buff);

    shm_id = -1;
}

Camera_Shared_Memory_R* Camera_Shared_Memory_R::get_Read_Shared_Memory()
{
	if(!Camera_Shared_Memory_R::sInstance)
	{
		Camera_Shared_Memory_R::sInstance = new Camera_Shared_Memory_R;
	}
	return Camera_Shared_Memory_R::sInstance;
}

int Camera_Shared_Memory_R::attach_Read_Shared_Memory()
{
    return Camera_Shared_Memory_R::shm_chn_attach();
}


int Camera_Shared_Memory_R::shm_chn_attach()
{
    shm_id = shmget((key_t)1225, 0, 0);	
    if(-1== shm_id)
    {
        ALOGI("[reverse_exe][%s][%d] share memory get error!\n",__func__, __LINE__);
        goto err;
    }

    shm_addr= shmat(shm_id, 0, 0);
    if((void *)-1== shm_addr)
    {
        ALOGI("[reverse_exe][%s][%d] share memory attach address error\n",__func__, __LINE__);
        goto err;
    }

    sharedLock_r = (mutex_sharedLock_t *)shm_addr;
    return 0;

err:
    return -1;
}


int Camera_Shared_Memory_R::open_Read_Shared_Memory(unsigned char *buffer)
{  
    //pthread_mutex_lock( &(sharedLock_r->lock) );
    if (0 == pthread_mutex_trylock( &(sharedLock_r->lock))) {

        memcpy(buffer, ((pthread_mutex_t *)shm_addr)+1, MAX_BUF_SIZE);
        ALOGI("[reverse_exe][%s][%d] buffer -- %x-%x-%x-%x - %x-%x-%x-%x - %x-%x-%x-%x",__func__,__LINE__, 
                        buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],
                        buffer[7],buffer[8],buffer[9],buffer[10],buffer[11]);

        pthread_mutex_unlock( &(sharedLock_r->lock) );
    }else{
        ALOGI("[reverse_exe][%s][%d] lock is busy \n",  __func__,__LINE__);
        return -1;
    }

    return 0;
}


int Camera_Shared_Memory_R::close_Read_Shared_Memory()
{

    ALOGI("[%s][%d] shm_id=%d, shm_addr=%p \n",  __func__,__LINE__, shm_id, shm_addr);
    // release shm_addr
    if ((shm_addr != NULL) && shmdt(shm_addr) == -1)
    {
        ALOGI("[%s][%d] shmdt error!,shm_addr=%p \n",  __func__,__LINE__, shm_addr);
        return -1;
    }

    return 0;
}

//////////////////////////////////////////////////////////////////////////////////////
// save yuv file in /sdcard/reverse/Rear-Camera-720x480-0.yuv

static int index = 0;

void Camera_Shared_Memory_R::Camera_Shared_Memory_Dump(unsigned char * buf, int size)
{
    char filename_buf[128];

    if(index >= 200){
        ALOGI("[reverse_exe][%s][%d] index=%d ,too big \n",__func__, __LINE__, index);    
        return;
    }

    if(access(REVERSE_CAMERA_DUMP_LOCATION,F_OK) != 0){
		printf("create new path!\n");
		mkdir(REVERSE_CAMERA_DUMP_LOCATION, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);  
	}

	snprintf(filename_buf, sizeof(filename_buf), "%sRear-Camera-720x480-%d.yuv", REVERSE_CAMERA_DUMP_LOCATION,  index);
    ALOGI("[reverse_exe][%s][%d] filename_buf=%s  \n",__func__, __LINE__, filename_buf);

    int file_fd = open(filename_buf, O_RDWR | O_CREAT, 0777);	

    ssize_t written_len = 0;

    if (file_fd >= 0){
        fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        write(file_fd, buf, MAX_BUF_SIZE);	
		close(file_fd);
        index ++;								
    }else{
        ALOGE("%s: fail t open file for image dumping", __func__);
    }
}

3. 測試Daemon代碼 H264_Reverse.cpp

# nativecamerasdk/native_camera_impl.cpp

//[email protected] +++
#include "video/H264_Reverse.h"      

DMSDPSendBackDataCB reverse_sendbackFrameFunc = nullptr;
static int reverse_capturing = 0;

// 註冊Camera 數據回調函數
int32_t CameraRegisterSendDataCallback(const char* id, uint32_t idLen, const DMSDPSendBackDataCB cb)
{
    /* regist callback senddata */
    ALOGI("CameraRegisterSendDataCallback");

    // [email protected] +++
    if( strcmp(id, "5") == 0 ) {			// id = 5, reverse_camera
        reverse_sendbackFrameFunc = cb;
    }
    return DMSDP_NO_ERROR;
}

// 數據採集線程
void * cap_reverse (void *arg)
{
	ALOGI("[reverse_exe][%s][%d] Enter ... \n",__func__, __LINE__);
    // 1. init
    Camera_Shared_Memory_R * Camera_Shared_Memory_r = Camera_Shared_Memory_R::get_Read_Shared_Memory();
    
	while(reverse_capturing)
	{
        memset(Camera_Shared_Memory_r->shm_addr_buff, 0, MAX_BUF_SIZE);
        // 2. read shm data
        Camera_Shared_Memory_r->open_Read_Shared_Memory(Camera_Shared_Memory_r->shm_addr_buff);
        // 3. daemon ,save data with yuv file
        Camera_Shared_Memory_r->Camera_Shared_Memory_Dump(Camera_Shared_Memory_r->shm_addr_buff , MAX_BUF_SIZE);

        // here call callback send buff
        //sendbackFrameFunc( id_s , sizeof(id_s), Camera_Shared_Memory_r->shm_addr_buff, MAX_BUF_SIZE, (int32_t)DMSDPCameraDataType::H264);
        
        usleep(30000);  //sleep 30ms
	}
	pthread_exit(NULL);
}

// 打開攝像頭,開始啓動數據採集線程
int32_t OpenCamera(const DMSDPCameraParam* param) {
    if (param == nullptr) {
        ALOGE("%s: open camera param is null", __FUNCTION__);
        return DMSDP_ERR_INVALID_PARAMETER;
    }

    ALOGI("[reverse_exe][%s][%d] id=%s \n",__func__, __LINE__, param->id);
    if( strcmp(param->id, "5") == 0 )		// id = 5, reverse_camera
    {	
    	// init share memory 
        Camera_Shared_Memory_R * Camera_Shared_Memory_r = Camera_Shared_Memory_R::get_Read_Shared_Memory();
        reverse_capturing = 1;

        // start pthread
        pthread_t pthreadReverse;
        if (pthread_create(&pthreadReverse, nullptr, cap_reverse, nullptr))
            ALOGI("%s: Create cap_reverse error!", __FUNCTION__);

        if (pthreadReverse != 0)
        {
            pthread_detach(pthreadReverse);
            ALOGI("%s: capture h264 preview exit", __FUNCTION__);
        }
    }
    ALOGI("%s: open camera success", __FUNCTION__);
    return DMSDP_NO_ERROR;
}

// 關閉數據採集
int32_t CloseCamera(const char* id, uint32_t idLen)
{
    if( strcmp(id, "5") == 0 ){
        reverse_capturing = 0;
    }
    return DMSDP_NO_ERROR;
}

// Daemon 主函數,後續,該部分調用由華爲來實現
int main(void)
{
    char id_test[] = "5";
    const char *id_pt = id_test;
    DMSDPCameraParam param_test;
    param_test.id = id_pt;
    
    // 1. register  callback 
    // CameraRegisterSendDataCallback

    // 2. open camera get data
    OpenCamera(&param_test);
    
    while(1){
        sleep(10);
    }
    return 0;
}

三、Daemon 實測

1. 發送端log 輸出

通過 PCAN ,往車機發送倒車命令後,進入倒車模式,開啓倒車攝像頭,
當有數據輸出時,會初始化共享內存,創建 共享 buffer ,開始發送數據

ciellee@sh:~/tamp$ adb logcat -b all | grep Shared_Memory
05-29 10:50:45.740   798   930 I         : [create_Shared_Memory][46] shm_id : 0
05-29 10:50:45.741   798   930 I         : [create_Shared_Memory][67] add shm_id=0, shm_addr=0xb2887000 

2. 接收端log 輸出

執行可執行程序: msm8937_32go:/ # libdmsdpcamerahandler_exe
掛接共享內存後,開始讀取共享內存數據,並保存爲yuv 圖片。

05-29 10:51:12.932  7616  7616 I CamSDK_3rdCamera: [reverse_exe][OpenCamera][569] id=5 
05-29 10:51:12.939  7616  7618 I CamSDK_3rdCamera: [reverse_exe][cap_reverse][543] Enter ... 
05-29 10:51:12.957  7616  7618 I : [reverse_exe][open_Read_Shared_Memory][84] buffer -- d2-d2-d2-d2 - d2-d2-d2-d2 - d2-d2-d2-d2
05-29 10:51:12.967  7616  7618 I : [reverse_exe][Camera_Shared_Memory_Dump][132] filename_buf=/sdcard/reverse/Rear-Camera-720x480-0.yuv  
05-29 10:51:13.004  7616  7618 I : [reverse_exe][open_Read_Shared_Memory][84] buffer -- d2-d2-d2-d2 - d2-d2-d2-d2 - d2-d2-d2-d2
05-29 10:51:13.004  7616  7618 I : [reverse_exe][Camera_Shared_Memory_Dump][132] filename_buf=/sdcard/reverse/Rear-Camera-720x480-1.yuv  
05-29 10:51:13.041  7616  7618 I : [reverse_exe][open_Read_Shared_Memory][84] buffer -- d2-d2-d2-d2 - d2-d2-d2-d2 - d2-d2-d2-d2
05-29 10:51:13.041  7616  7618 I : [reverse_exe][Camera_Shared_Memory_Dump][132] filename_buf=/sdcard/reverse/Rear-Camera-720x480-2.yuv  
05-29 10:51:13.083  7616  7618 I : [reverse_exe][open_Read_Shared_Memory][84] buffer -- d2-d2-d2-d2 - d2-d2-d2-d2 - d2-d2-d2-d2

3. 導出YUV 圖片

ciellee@sh:~/tamp$ adb pull /sdcard/reverse/ .
pull: building file list...
pull: /sdcard/reverse/Rear-Camera-720x480-47.yuv -> ./Rear-Camera-720x480-47.yuv
pull: /sdcard/reverse/Rear-Camera-720x480-46.yuv -> ./Rear-Camera-720x480-46.yuv
pull: /sdcard/reverse/Rear-Camera-720x480-45.yuv -> ./Rear-Camera-720x480-45.yuv
pull: /sdcard/reverse/Rear-Camera-720x480-44.yuv -> ./Rear-Camera-720x480-44.yuv
pull: /sdcard/reverse/Rear-Camera-720x480-43.yuv -> ./Rear-Camera-720x480-43.yuv
pull: /sdcard/reverse/Rear-Camera-720x480-42.yuv -> ./Rear-Camera-720x480-42.yuv

查看圖片:
ffplay -video_size 720x480 -pix_fmt nv21 -i Rear-Camera-720x480-40.yuv

如下是獲取的 pattern 圖:
在這裏插入圖片描述


四、下一步工作

現在共享內存 Deamon 寫好了,已經發郵件請華爲安排一位研發和我對接聯調。
所以接下來兩件事:

  1. 和華爲工程師聯調 Hicar 倒車影像功能
  2. 使用C++ ADIL 來代替 共享內存 ,實現進程間大數據傳輸

參考:《Linux進程間互斥鎖 (共享內存實現)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章