您尚未登录。

楼主 #1 2018-04-03 09:57:24

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/oldcdr.html

可以改进的地方
设置白平衡,曝光等参数的时候,最好可以看到预览
回放预览窗口中可以加一个文件过滤的功能:

按时间过滤

按文件类型过滤

需要解决的问题
配置文件中pixels ARGB 和 ABGR的问题

优化cdr启动时间

实现回放预览窗口中的图像预览。

TODO:

处理TF卡状态发生变化时,每个窗口的响应 回放列表循环 播放状态下,调整快进与快退, 快退的效果不明显。 暂停的时候,按快退或者快进会自动播放. 回放时,长按快进, 短按音量 如果启动的时候没有找到配置文件menu.cfg, 将会采用默认的英文界面, 但是在打开子菜单,却发现是中文的. 回放预览显示 设置预览帧率, HerbCamera->setPreviewFrameRate csi和UVC录像得到的视屏时间长度不同。 低电量的提示, 10S 自动关机, 拔火牛时 提示, 10s自动关机。

done at 2014-08-05   
how: (改为在record_front线程中insert database就可以避免这个问题, 和保护fron_db_info互斥访问的问题)
FIXED List:

进入子菜单后按mode键退出, 发现配置文件中current中被写入了-1.    fixed
2014-08-04 Take Picture    done 播放异常退出后,Alpha没有关闭 如Phtograh切换菜单后,再切换回来后状态栏图标不一致。    done
(是因为在MSG_SHOWWINDOW中没有判断current_state)    fixed 2014-08-04 双路录像时duration到达时,会有一路插入数据库失败.
由于对数据库的访问没有加锁 录像时,先更换已有的预分配文件,再预分配下一次的文件。 在使用每个thread_data都需要加锁,因为有可能这个变量正被释放, 比如快速按ok键,启动和停止录像,就会出现thread_data已经被释放掉了,却还在使用这个变量. 回放 PlayBack.cpp MWM_CHANGE_FROM_WINDOW 文件路径的原因导致 不能播放移动侦测文件。 启动时先预分配好一些文件,发现pre_alloc thread只被唤醒了一次 切换到PlayBackPreview的时候,数据库中记录的总数有的时候不正确

to fix: Mainwindow.cpp(msg): line:[0206] update_database() sql is INSERT INTO CdrFile VALUES('20000101_062159A.MP4',946707719,'video',1,0), tffiles[0] is 20000101_062159A.MP4 , executeSQL() [302], code=19 errmsg=UNIQUE constraint failed: CdrFile.file





离线

楼主 #2 2018-04-03 09:58:02

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-07-29.html

录像预览window有3种状态:
typedef enum {
    Preview = 1,
    Record,
    PhotoGraph   
}RecordPreviewStatus;
3种状态之间如何切换
在MSG_CREATE中调用init_window_data初始化:

static int init_window_data(HWND hWnd)
{
    rPreviewWndData->status = Preview;
    return 0;
}
在MSG_CREATE种判断是否需要上电录像,如果是,则设置status为Record

在程序运行过程中, status的状态通过按Mode键来切换。   
Preview/Record --> PhotoGraph --> Playback --> Preview/Record

从其他窗口切换过来的时候,收到Mainwindow发过来的MWM_CHANGE_FROM_WINDOW, 可以知道是从哪个窗口切换过来的, 这个时候可以重新设置status

Preview/Record的状态通过按OK键切换

    if(status == Preview || status == Record) {
        if(Mode short press) {
            if(status == Preview)   
                status = Record
            else if (status == Record)
                status = Preview
        }
    }





离线

楼主 #3 2018-04-03 09:58:13

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-07-30.html

使用录像的回调函数
HerbMediaRecorder::setMaxDuration    设置最大时间

回调CedarXRecorder::dataCallbackTimestamp

if (mMaxFileDurationUs != 0 mListener->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);

MEDIA_RECORDER_INFO_MAX_DURATION_REACHED 回调可以这样写 class OnInfoListener : public HerbMediaRecorder::OnInfoListener { public:    OnInfoListener(需要的信息 *arg):mPriv(arg){}; bool onInfo(HerbMediaRecorder *pMr, int what, int extra) { fd = getNewFd(); pMr->setOutputFileSync(fd); } private: 需要的信息* const mPriv; };

OnInfoListener mOnInfoListener(需要的信息指针); mHMR->setOnInfoListener(&mOnInfoListener);

TODO:

修改录像流程:
之前的策略是, 使用照录像时长作为间隔,定时启动和关闭录像线程,由于需要实现碰撞加锁,所以需要录像不能停止,否则会有一个时间间隙,导致有可能丢失碰撞前后的数据 现在的流程为: 除非手动停止录像,否则录像线程应该一直运行下去,并设置录像时长的MaxDuration, 这个值即录像时长.添加录像的回调函数,通知应用程序录像已完成。
thread: pre_alloc    run record_thread() { thread:    record_front thread: record_rear thread: record_others } Problems: record_thread如何管理上面的多个线程:

如何控制预分配线程:

#if WITH_PRE_ALLOC
    pre_alloc事先已经运行, 等待条件变量:
    激活pre_alloc的方法:
        pthread_mutex_lock(&pre_alloc_mutex);
        pthread_cond_signal(&pre_alloc_cond);
        pthread_mutex_unlock(&pre_alloc_mutex);
    获取预分配文件的文件名:
        ptr = get_pre_alloc_file(pre_alloc_files);
    根据当前的时间,重命名预分配文件名:
        bzero(filename, sizeof(filename));
        now = set_video_filename(filename, CAMERA_FRONT);
        sprintf(buf, "%s%s", CON_2STRING(TF_CARD_PATH, VIDEO_DIR), filename);
        buf[strlen(TF_CARD_PATH) + strlen(VIDEO_DIR) + strlen(filename)] = '\0';
        db_msg("buf is %s\n", buf);
        rename(ptr, buf);
    清空预分配buffer,pre_alloc通过判断这个buffer如果位空,那么表示文件以被取走:
        pthread_mutex_lock(&pre_alloc_mutex);
        bzero(ptr, CDR_FILE_LENGHT);
        pthread_mutex_unlock(&pre_alloc_mutex);
    打开文件预分配文件:
        if((fd = open(buf, O_RDWR)) == -1) {
            db_error("open %s failed: %s\n", buf, strerror(errno));
            unlink(buf);
            continue;
        }
#else
    pre_alloc事先已经运行, 等待条件变量:
    激活pre_alloc的方法:
        pthread_mutex_lock(&pre_alloc_mutex);
        pthread_cond_signal(&pre_alloc_cond);
        pthread_mutex_unlock(&pre_alloc_mutex);
       
    获取预分配文件名:   
        bzero(filename, sizeof(filename));
        now = set_video_filename(filename, CAMERA_FRONT);
        sprintf(buf, "%s%s", CON_2STRING(TF_CARD_PATH, VIDEO_DIR), filename);
        buf[strlen(TF_CARD_PATH) + strlen(VIDEO_DIR) + strlen(filename)] = '\0';
    打开文件预分配文件:
        if((fd = open(buf, O_RDWR | O_CREAT, 0777)) == -1) {
            db_error("open %s failed: %s\n", buf, strerror(errno));
            unlink(buf);
            continue;
        }   
#endif
record_manager_thread要完成的功能:

管理多个录像线程的启动与停止(通过显示模式判断改启动或停止哪些线程)
伪代码: wait record event (know start which record, or stop which record) if(start) {

}

record_thread_xxx要完成的功能:

控制预分配线程,得到预分配文件的fd (通过录像完成的回调来通知) 重新设置outputfile fd





离线

楼主 #4 2018-04-03 09:58:47

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-07-31.html

使用HerbMediaRecorder的回调函数,通知录像完成
如果使用了 mHMR->setMaxDuration(seconds * 1000); , 那么在listener里面会收到 MEDIA_RECORDER_INFO_MAX_DURATION_REACHED    这个消息, 然后通知录像线程继续

class OnInfoListener : public HerbMediaRecorder::OnInfoListener
{
public:
    OnInfoListener(thread_data *arg):record_thread_data(arg){}
    virtual ~OnInfoListener(){}
    void onInfo(HerbMediaRecorder *pMr, int what, int extra)
    {
        switch(what)
        {
        case MEDIA_RECORDER_INFO_EXTRA_FILE_DONE:
            {
                db_msg("finish recodering extra file.\n");
                //                last_extra_finished = true;  //fix -> atomic operation
            }
            break;
        case MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:
            {
                db_msg("reached max duration.\n");
                pthread_mutex_lock(&record_thread_data->mutex);
                pthread_cond_signal(&record_thread_data->cond);
                pthread_mutex_unlock(&record_thread_data->mutex);
            }
            break;
        default:
            break;
        }
    }
private:
    thread_data *record_thread_data;
};
注意:

SetOutFile(fd) 在prepare之前调用, 在stop之前要切换文件就使用setOutFileSync(fd)
setMexDuration(xxx);
setOutputFile(fd);
prepare();
start();
setOutputFileSync(fd);
setOutputFileSync(fd);
...
setOutputFileSync(fd);
stop();
添加碰撞加锁的支持
正常文件
/mnt/extsd/video/xxx.MP4
加锁文件
/mnt/extsd/lock/xxx_impact.MP4





离线

楼主 #5 2018-04-03 10:01:35

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-04.html

测试碰撞之后,收不到extrafile完成的消息
初步判断,是调用 setOutputFileSync 导致的, 还不确定。

添加拍照功能
API:

void HerbCamera::takePicture(ShutterCallback *pShutter, PictureCallback *pRaw, PictureCallback *pPostview, PictureCallback *pJpeg)

拍照前设置拍照模式





离线

楼主 #6 2018-04-03 10:01:45

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-05.html

添加 uvc摄像头 (USB video class 或USB video device class)
UVC是Microsoft与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标准,目前已成为USB org标准之一。
修改.config
要编译产生uvcvideo.ko需要修改config文件: linux-3.4/arch/arm/configs/sun7ismp_defconfig

CONFIG_USB_VIDEO_CLASS=m

同时删除linux-3.4/.config, 到camlinux目录执行mklichee会自动将sun7ismp_defconfig拷贝到.config

修改init.rc
编辑device/softwinner/pluto-common/init.rc 加入 insmod /system/vendor/modules/uvcvideo.ko
修改camera.cfg
edit camlinux/device/softwinner/pluto-cdr/configs/camera.cfg, set number_of_camera with 2

uvc的驱动位于 linux-3.4/drivers/media/video/uvc





离线

楼主 #7 2018-04-03 10:02:13

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-06.html

添加显示模式:

typedef enum {
    CSI_ONLY = 1,
    UVC_ONLY,
    UVC_ON_CSI,
    CSI_ON_UVC,
    NO_VIDEO
}pip_mode_t;        /* define the Picture-in-Picture mode */
状态转移图如下:

PIP_MODE状态转移图
PIP_MODE状态转移图表格
切换显示模式的2个原则:

保证不需要显示的Layer是处于关闭状态的 保证Rect大的Layer在下面,小的在上面.
所以得到切换的代码如下:

                      pthread_mutex_lock(&status_mutex);
                    if(pip_mode == NO_VIDEO) {
                        pthread_mutex_unlock(&status_mutex);
                        break;   
                    }
                    /* chang the pip_mode */
                    if(pip_mode == UVC_ON_CSI) {
                        mCD_front->exchangeSurface(hlay_front, hlay_rear, 1);
                        pip_mode = CSI_ON_UVC;   
                        pthread_mutex_unlock(&status_mutex);
                        db_msg("-----------PIP_MODE: UVC_ON_CSI ---> CSI_ON_UVC\n");
                        /* do something */
                    } else if(pip_mode == CSI_ON_UVC) {
                        if(close_layer(hlay_front) < 0) {
                            pthread_mutex_unlock(&status_mutex);
                            break;
                        }
                        pip_mode = UVC_ONLY;
                        pthread_mutex_unlock(&status_mutex);
                        db_msg("-----------PIP_MODE: CSI_ON_UVC ---> UVC_ONLY\n");
                    } else if(pip_mode == UVC_ONLY) {
                        if(CSI_EXSIST) {
                            if(close_layer(hlay_rear) < 0) {
                                pthread_mutex_unlock(&status_mutex);
                                break;
                            }
                            if(open_layer(hlay_front) < 0) {
                                pthread_mutex_unlock(&status_mutex);
                                break;
                            }

                            mCD_front->exchangeSurface(hlay_front, hlay_rear, 1);

                            pip_mode = CSI_ONLY;
                            pthread_mutex_unlock(&status_mutex);
                            db_msg("-----------PIP_MODE: UVC_ONLY ---> CSI_ONLY\n");
                        } else {
                            pthread_mutex_unlock(&status_mutex);
                        }
                    }
                    else if(pip_mode == CSI_ONLY) {
                        if(UVC_EXSIST) {
                            if(open_layer(hlay_rear) < 0) {
                                pthread_mutex_unlock(&status_mutex);
                                break;
                            }

                            pip_mode = UVC_ON_CSI;
                            pthread_mutex_unlock(&status_mutex);
                            db_msg("-----------PIP_MODE: CSI_ONLY ---> UVC_ON_CSI\n");
                        } else {
                            pthread_mutex_unlock(&status_mutex);
                        }
                    } else {
                        db_error("invalid PIP MODE: %d\n", pip_mode);
                        pthread_mutex_unlock(&status_mutex);
                    }
UVC插拔的处理

UVC录像和回放的处理





离线

楼主 #8 2018-04-03 10:02:28

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-08.html

更改current_state中STATUS_RECORD和STATUS_PREVIEW之间切换的处理
这两种状态的切换只能放在录像线程里面处理.
如果其中一个录像线程在进行中,那么current_state = STATUS_RECORD 如果两个录像线程都已经停止,那么current_state = STATUS_PREVIEW
解决从RecordPreview窗口切换到PlaybackPreview窗口时, 预览关闭和surface释放的问题:
RecordPreview ---> PlaybackPreview
1. CSI camera stop preview 2. CSI camera release surface 3. uvc camera close layer

PlaybackPreview ---> RecordPreview
1. request layer for csi 2. 根据pip_mode恢复切换之前csi layer的大小和位置 3. uvc camera open layer 4. csi camera start preview

处理插拔 UVC 摄像头时, 停止录像的问题





离线

楼主 #9 2018-04-03 10:02:36

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-11.html

修改预分配策略:

启动时,先预分配好文件。包括normal video, impact video, motion detect video, 总共3个文件 录像过程中先更换文件,再预分配下一次的文件。
static pre_alloc_t pre_alloc_files[2][PRE_ALLOC_BUFFER_COUNT];

其中

buffer[0] -- buffer[1]    is for normal video file. buffer[2] -- buffer[3]    is for the impact video file buffer[4] -- buffer[5]    is for the motion detect video file
so PRE_ALLOC_BUFFER_COUNT must great than 6

record 线程的流程:

首先能够进入到录像线程的前提是已经获得了预分配的文件 设置参数, listener ... start 继续为下一次预分配文件,得到文件描述符,存入data->fd.(这个时候已经在另外的线程中往之前预分配的文件中写入数据,所以不会影响本次录像) 等待duration到达(pthread_cond_wait(&rear_data->cond, &rear_data->mutex);) 如果data->fd有效,则重新设置fd 更新上一次录像的数据库信息 如果data->fd有效则替换数据库信息(例: rear_db_info = db_info_bak), 如果data->fd无效,则表示预分配失败,需要退出录像线程
在这个流程中有一个问题:

在为下一次录像预分配好文件之后并没有关闭文件描述符, 关闭文件描述符的时机是重新设置文件描述符之后,那么再duration没有到达之前之前这个文件一直处于打开状态:如果这个时候拔卡会怎样:

拔卡的时候会主动给RecordPreview窗口发消息,停止录像,所以等待的条件会立即返回,然后关闭文件描述符。

那如何避免主动停止录像后又重新设置文件描述符?

因为停止录像的方式是: 先设置data->run, 然后产生条件, 所以只需要在重新设置文件描述符之前判断data->run

代码如下:

    mHMR->start();
    db_msg("==================== record_rear start recording ...\n");
    pthread_mutex_lock(&rear_data->run_mutex);
    while(data->run == 1)
    {
        pthread_mutex_unlock(&rear_data->run_mutex);

        pthread_mutex_lock(&current_state_mutex);
        status_record_rear = 1;
        current_state = STATUS_RECORD;   
        pthread_mutex_unlock(&current_state_mutex);

        db_msg("======================= Recording... filename is %s\n", rear_db_info.filename);

        /* now the record is going on, prepare the next file*/
        retries = 5;
        while(retries > 0)
        {
            param.camera_index = CAMERA_REAR;
            param.size = SZ_1M * 100;
            param.type = 0;
            if((data->fd = wakeup_pre_alloc(&param, &db_info_bak)) <= 0) {
                db_msg("pre alloc file failed, retry again!\n");
                retries--;
            } else {
                break;   
            }
        }

        pthread_cond_wait(&rear_data->cond, &rear_data->mutex);
        pthread_mutex_unlock(&rear_data->mutex);
        db_msg("==================== this duration reached ...\n");

        /* change another file, and save the last file to db */
        if(data->fd > 0 && data->run == 1) {
            mHMR->setOutputFileSync(data->fd);
            close(data->fd);
        }
       
        /* insert record to database */
        if(dbc != NULL) {
            rear_db_info.flag = 1;              /* completion */
            dbc->setRecord(String8("file"), (void*)  rear_db_info.filename); /* filename time and type is set in the wakeup_pre_alloc */
            dbc->setRecord(String8("time"), (void*) &rear_db_info.time);
            dbc->setRecord(String8("type"), (void*)  rear_db_info.type);
            dbc->setRecord(String8("vtl"),  (void*) &rear_db_info.vtl);        /* be set, after call the set_duration */
            dbc->setRecord(String8("flag"), (void*) &rear_db_info.flag);
            dbc->insertRecord();
        } else {
            db_warn("========== invalid dbc, not update the database ======= \n");
        }   

        if(data->fd > 0) {
            rear_db_info = db_info_bak;   
        } else {
            db_error("pre_alloc invalid fd\n");
            break;
        }

        pthread_mutex_lock(&rear_data->run_mutex);
    }





离线

楼主 #10 2018-04-03 10:02:49

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-12.html

1.图像质量接口

mHMR->setVideoSize
HD:1280*720

FHD:1920*1080

2. 移动侦测

侦测到移动物体(onAWMoveDetection回调返回值为1)开始录像连续侦测到5秒以上不动(回调返回值为0),就停止录像。
预分配1min(60M)的大小

3.碰撞检测前5后10,预分配15M

发现移动侦测必须要在startpreview之后才能启动成功。





离线

楼主 #11 2018-04-03 10:02:59

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-13.html

向thread_data中添加了两个变量, flag1 和 flag2, 修正了 pthread_cond使用过程中可能出现的竞态 和 虚假唤醒的问题:

对pre_alloc_files加锁保护





离线

楼主 #12 2018-04-03 10:03:20

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-18.html

回放预览-》mode长按出菜单,菜单选项目前就一项:删除-》按ok-》弹出是否删除对话框

secondary dc的特效:

/* 弹出式效果 */
static void effect_pop_out(HWND hDlg)
{
    RECT rect;
    HDC sec_dc;

    GetWindowRect(hDlg, &rect);
    printf("left is %d\n", rect.left);
    printf("top is %d\n", rect.top);
    printf("right is %d\n", rect.right);
    printf("bottom is %d\n", rect.bottom);
    sec_dc = GetSecondaryDC(hDlg);

    StretchBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, RECTW(rect)/5, RECTH(rect)/5, 0);
    usleep(50000);

    StretchBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, RECTW(rect) * 2/5, RECTH(rect) * 2/5, 0);
    usleep(50000);

    StretchBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, RECTW(rect) * 3/5, RECTH(rect) * 3/5, 0);
    usleep(50000);

    StretchBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, RECTW(rect) * 4/5, RECTH(rect) * 4/5, 0);
    usleep(50000);

    SetMemDCAlpha(sec_dc, 0, 0);
    BitBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, 0);
    SetSecondaryDC(hDlg, sec_dc, ON_UPDSECDC_DEFAULT);
}

/* 淡入淡出效果 */
static void effect_fade(HWND hDlg)
{
    RECT rect;
    HDC sec_dc;

    GetWindowRect(hDlg, &rect);
    printf("left is %d\n", rect.left);
    printf("top is %d\n", rect.top);
    printf("right is %d\n", rect.right);
    printf("bottom is %d\n", rect.bottom);
    sec_dc = GetSecondaryDC(hDlg);

    SetMemDCAlpha(sec_dc, MEMDC_FLAG_SRCALPHA, 64);
    BitBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, 0);
    usleep(100000);

    SetMemDCAlpha(sec_dc, MEMDC_FLAG_SRCALPHA, 128);
    BitBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, 0);
    usleep(100000);

    SetMemDCAlpha(sec_dc, 0, 0);
    BitBlt(sec_dc, 0, 0, RECTW(rect), RECTH(rect), HDC_SCREEN, rect.left, rect.top, 0);

    SetSecondaryDC(hDlg, sec_dc, ON_UPDSECDC_DEFAULT);
}





离线

楼主 #13 2018-04-03 10:03:33

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-25.html

打补丁
work/a10t/patch/patch0825.tar.gz

git am是使用:

将 git format-patch 生成的patchy引入到自己的代码库中(里面包含了提交的日志,作者,日期等信息):

使用git-am之前, 你要首先git am –abort 一次,来放弃掉以前的am信息,这样才可以进行一次全新的am。

不然会遇到这样的错误。 .git/rebase-apply still exists but mbox given.

若发生冲突,使用下面的命令apply补丁 git apply --reject 0001.patch 查看*.rej文件修改源文件后再次git add文件 若报whitespace的警告,可以加上下面的参数 --ignore-space-change --ignore-whitespace --whitespace=nowarn

├── camlinux
│   ├── 0001-Support-capture-a-Bitmap-containing-a-representative.patch
│   ├── 0002-fix-hwdisplay-bug-screen-is-blurred-when-exchanged.patch
│   ├── 0003-modify-the-display-framerate-to-30fps.patch
│   └── 0004-add-fallocate.patch
└── lichee
    ├── brandy
    │   ├── 0001-fix-lcd-bug.patch
    │   ├── 0002-rm-uboot-some-log.patch
    │   └── 0003-reduce-time-for-optimize.patch
    ├── linux-3.4
    │   ├── 0001-fix-showlogo-issue-and-rm-some-log.patch
    │   └── 0002-rm-some-driver-for-optimize.patch
    └── tools
        ├── 0001-fix-LCD-bug.patch
        ├── 0002-fix-show-logo-issue.patch
        ├── 0003-reduce-time-for-optimize.patch
        ├── 0004-optimize-uboot-time-when-boot.patch
        └── 0005-update-cfg.fex-for-miniGUI-cfg.patch
camlinux 0001 提供视频图像预览的接口 camlinux 0002 解决uvc和csi layer交换时屏幕闪烁的问题. camlinux 0004 将预分配的功能集成到framework里面

添加data分区
从norflash里面分出一个可读写的分区

修改分区配置:

lichee/tools/pack/chips/sun7i/configs/linux/default/sys_partition.fex

[partition] name = cfg size = 1024 downloadfile = "cfg.fex" user_type = 0x8000

分区的名称位Cfg, 分区的大小为 1024个扇区, 每个扇区的大小是512Byte, 那么cfg分区的大小就是512KB

下载的文件位cfg.fex, 是相对于image.cfg的路径, 例如: lichee/tools/pack/out

$ file cfg.fex cfg.fex: Linux jffs2 filesystem data little endian

制作cfg.fex的方法
例如新建一个data目录:

$ ls data/ 480X272.cfg menu.cfg

mkfs.jffs2 -d data -o cfg.fex

将生成的文件拷贝到 lichee/tools/pack/chips/sun7i/configs/linux/cdr

安装jffs2工具
下载 linux - mtd-snapshot 工具, 编译并安装即可





离线

楼主 #14 2018-04-03 10:03:58

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-26.html

添加change_pip_mode的函数统一管理画中画模式的切换:

画中画模式的切换有4种触发条件,状态转移图如下:

画中画模式切换的状态转移图

从STATUS_PREVIEW 切换到 Menu菜单, 或者切换到拍照模式前, 用pip_mode_bak保存当前的pip_mode

如果是切换到拍照模式,那么统一把pip_mode切换为CSI_ONLY, 然后从其他窗口切换回录像预览窗口时,

根据pip_mode_bak恢复pip模式





离线

楼主 #15 2018-04-03 10:04:15

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-08-29.html

解决UVC不能录像的问题:

现象:

一开始录像,UVC就停止预览。

原因: 在初始化uvc camera的时候没有设置 params.setVideoSize(1280, 720);

log: V/CameraHardware2( 967): (f:startRecording, l:1106)VideoCapture:640x480, Capture:1280x720

这两个大小不同,导致无法开始录像:

device/softwinner/common/hardware/camera/CameraHardware2.cpp

status_t CameraHardware::startRecording()
{
    LOGV("(f:%s, l:%d)VideoCapture:%dx%d, Capture:%dx%d", __FUNCTION__, __LINE__, mVideoCaptureWidth, mVideoCaptureHeight, mCaptureWidth, mCaptureHeight);
    if (mVideoCaptureWidth != mCaptureWidth || mVideoCaptureHeight != mCaptureHeight)
    {
        doStopPreview();
        doStartPreview();
    }
}
具体原因待查

录像过程中对文件加锁





离线

楼主 #16 2018-04-03 10:04:30

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

http://wiki.linuxtoy.cn/WorkLog/worklog_2014-09-01.html

log
20:51:59.872: root@android:/ #    ^^^^^^^^^^^^^^^^^^^^^^^^^^ in MiniGUI main_entry time is 47 secs, 494186693 nsecs 20:52:00.888: V/Mainwindow.cpp line[1109] MiniGUIAppMain()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ start cdr, time is 47 secs, 795755109 nsecs 20:52:00.983:    ^^^^^^^^^^^^^^^^^^^^^^^ init_global_data , time is 48 secs, 59881234 nsecs 20:52:01.012: V/Mainwindow.cpp line[1166] MiniGUIAppMain()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 65991859 nsecs

20:52:01.149: V/Mainwindow.cpp line[0880] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 67561859 nsecs 20:52:01.168: V/Mainwindow.cpp line[0890] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 69468943 nsecs 20:52:01.198: V/Mainwindow.cpp line[0897] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 70774193 nsecs

20:52:01.207: V/cdr line[0134] create_windows()( 1016): ^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 70916276 nsecs 20:52:02.479: V/cdr line[0154] create_windows()( 1016): ^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 777987193 nsecs 20:52:02.549: V/cdr line[0174] create_windows()( 1016): ^^^^^^^^^^^^^^^^^^^^^ time is 48 secs, 983287943 nsecs 20:52:02.582: V/cdr line[0194] create_windows()( 1016): ^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 26243985 nsecs 20:52:02.591: V/cdr line[0212] create_windows()( 1016): ^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 50553901 nsecs

20:52:02.638: V/Mainwindow.cpp line[0905] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 51580360 nsecs 20:52:02.647: V/Mainwindow.cpp line[0919] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 51739651 nsecs 20:52:02.670: V/Mainwindow.cpp line[0931] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 51973276 nsecs 20:52:02.692: V/Mainwindow.cpp line[0942] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 52151818 nsecs 20:52:02.702: V/Mainwindow.cpp line[0949] CDRWinProc()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 52279485 nsecs

20:52:02.711: V/Mainwindow.cpp line[1174] MiniGUIAppMain()( 1016): ^^^^^^^^^^^^^^^^^^^^^^^ time is 49 secs, 52306110 nsecs

==>

启动MiniGUI 花费了301ms

init_global_data 花费了 264 ms

CreateMainWindow 返回花费了 986 ms

init_window_data花费了 1.3 ms create_windows 花费了 980 ms

创建RecordPreview Window 花费了 700 ms    创建Menu Window 花费了206 ms 创建PlayBack Preview Window 花费了 42.9 ms 创建PlayBack Window花费了24 ms

需要优化的地方, init_global_data

get_db打开数据库需要花费200ms左右的时间。所以移到update_database,放到线程池里面做。

将创建窗口的create_windows分开位createRecordPreviewWindow 和 createOtherWindows.

createRecordPreviewWindow
16:10:04.430: /RecordPreview.cpp line[1218] RecordPreviewProc()( 1022): ^^^^^^^^^^^^^^^^^^^^^^^^ time is 84 secs, 112473666 nsecs 16:10:04.523: V/RecordPreview.cpp line[1230] RecordPreviewProc()( 1022): ^^^^^^^^^^^^^^^^^^^^^^^^ time is 84 secs, 119090208 nsecs 16:10:04.566: V/RecordPreview.cpp line[1240] RecordPreviewProc()( 1022): ^^^^^^^^^^^^^^^^^^^^^^^^ time is 84 secs, 126690249 nsecs 16:10:04.587: V/RecordPreview.cpp line[1265] RecordPreviewProc()( 1022): ^^^^^^^^^^^^^^^^^^^^^^^^ time is 84 secs, 127225791 nsecs 16:10:05.631: V/RecordPreview.cpp line[1287] RecordPreviewProc()( 1022): ^^^^^^^^^^^^^^^^^^^^^^^^ time is 84 secs, 635226458 nsecs

==> init_window_data 花费了 6.5ms createStatusBar 花费了 7.5ms 初始化CSI 并启动预览 花费了 510 ms

16:42:42.753: V/Mainwindow.cpp line[1090] MiniGUIAppMain()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 12 secs, 37455466 nsecs 16:42:43.543: V/Mainwindow.cpp line[1098] MiniGUIAppMain()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 12 secs, 370375466 nsecs

16:42:42.936: V/CreateWindow.cpp line[0099] createRecordPreviewWindow()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 12 secs, 38818883 nsecs 16:42:43.455: V/CreateWindow.cpp line[0130] createRecordPreviewWindow()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 12 secs, 367532591 nsecs

总共用了300ms启动 其中录像预览启动花了280 ms

启动CDR: 16:14:50.506: V/Mainwindow.cpp line[1067]    main()( 969): ^^^^^^^^^^^^^^^ in MiniGUI main_entry time is 11 secs, 516866258 nsecs 16:14:50.569: V/Mainwindow.cpp line[0858] InitRecordPreviewEx()( 969): ^^^^^^^^^^InitRecordPreviewEx time is 11 secs, 518473966 nsecs 16:14:50.580: V/Mainwindow.cpp line[0865] InitRecordPreviewEx()( 969): ^^^^^^^^^^startPreview time is 11 secs, 518612341 nsecs 16:14:50.590: V/RecordPreview.cpp line[1165] startPreview()( 969): ^^^^^^^^^^^^^ time is 11 secs, 518666341 nsec 16:14:50.613: V/RecordPreview.cpp line[1192] startPreview()( 969): ^^^^^^^^^^^^^ time is 11 secs, 752963509 nsec 16:14:50.622: V/RecordPreview.cpp line[1209] startPreview()( 969): ^^^^^^^^^^^^^ time is 11 secs, 753074259 nsec 16:14:50.631: V/CDRCamera.cpp line[0049] CDRCamera()( 969): ^^^^^^^^^^^ time is 11 secs, 754967675 nsec 16:14:50.650: V/Mainwindow.cpp line[1079] MiniGUIAppMain()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ start cdr, time is 11 secs, 968260383 nsecs 16:14:50.670: V/Mainwindow.cpp line[1132] MiniGUIAppMain()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969067967 nsecs 16:14:50.776: V/Mainwindow.cpp line[0902] CDRWinProc()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969644466 nsecs 16:14:50.786: V/Mainwindow.cpp line[0248]    init_window_data()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969667758 nsecs 16:14:50.795: V/Mainwindow.cpp line[0266]    init_window_data()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969685841 nsecs 16:14:50.805: V/Mainwindow.cpp line[0909]    CDRWinProc()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969745508 nsecs 16:14:50.814: V/CreateWindow.cpp line[0106] createRecordPreviewWindow()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969766425 nsecs 16:14:50.825: V/CreateWindow.cpp line[0120] createRecordPreviewWindow()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969788758 nsecs 16:14:50.859: V/RecordPreview.cpp line[1391]    RecordPreviewProc()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 969964591 nsecs 16:14:50.884: V/RecordPreview.cpp line[1403]    RecordPreviewProc()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 974361258 nsecs 16:14:50.927: V/RecordPreview.cpp line[1413]    RecordPreviewProc()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 983591550 nsecs 16:14:50.937: V/RecordPreview.cpp line[1421] RecordPreviewProc()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 983785717 nsecs 16:14:51.039: V/CreateWindow.cpp line[0139] createRecordPreviewWindow()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 984154842 nsecs 16:14:51.066: V/CreateWindow.cpp line[0148] createRecordPreviewWindow()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 984207217 nsecs 16:14:51.077: V/Mainwindow.cpp line[0919]    CDRWinProc()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 984226175 nsecs 16:14:51.086: V/Mainwindow.cpp line[1140]    MiniGUIAppMain()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 984247383 nsecs 16:14:51.158: V/Mainwindow.cpp line[0779]    LazyInit()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 985330633 nsecs 16:14:51.187: V/RecordPreview.cpp line[1432] RecordPreviewProc()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 985369467 nsecs 16:14:51.210: V/RecordPreview.cpp line[1465] RecordPreviewProc()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 11 secs, 985431592 nsecs 16:14:51.900: V/CDRCamera.cpp line[0060] CDRCamera()( 969): ^^^^^^^^^^^ time is 12 secs, 934134634 nsec 16:14:51.919: V/CDRCamera.cpp line[0071]    CDRCamera()( 969): ^^^^^^^^^^^ time is 12 secs, 934885592 nsec 16:14:51.927: V/RecordPreview.cpp line[1216]    startPreview()( 969): ^^^^^^^^^^^^^ time is 12 secs, 934938509 nsec 16:14:51.942: V/RecordPreview.cpp line[1224]    startPreview()( 969): ^^^^^^^^^^^^^ time is 12 secs, 934971467 nsec 16:14:52.535: V/RecordPreview.cpp line[1231]    startPreview()( 969): ^^^^^^^^^^^^^ time is 13 secs, 19691592 nsec 16:14:52.544: V/RecordPreview.cpp line[1240]    startPreview()( 969): ^^^^^^^^^^^^^ time is 13 secs, 19763842 nsec 16:14:52.769: V/RecordPreview.cpp line[1248]    startPreview()( 969): ^^^^^^^^^^^^^ time is 13 secs, 164646925 nsec 16:14:52.778: V/RecordPreview.cpp line[1258]    startPreview()( 969): ^^^^^^^^^^^^^ time is 13 secs, 164671175 nsec 16:14:52.787: V/Mainwindow.cpp line[0872]    InitRecordPreviewEx()( 969): ^^^^^^^^^^startPreview finished time is 13 secs, 164738967 nsecs 16:14:52.820: V/Mainwindow.cpp line[0786]    LazyInit()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 13 secs, 166534759 nsecs 16:14:52.880: V/CreateWindow.cpp line[0168]    createOtherWindows()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 13 secs, 311103259 nsecs 16:14:53.057: V/CreateWindow.cpp line[0198]    createOtherWindows()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 13 secs, 367021509 nsecs 16:14:53.298: V/CreateWindow.cpp line[0219]    createOtherWindows()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 13 secs, 623499050 nsecs 16:14:53.453: V/CreateWindow.cpp line[0238]    createOtherWindows()( 969): ^^^^^^^^^^^^^^^^^^^^^ time is 13 secs, 696772217 nsecs 16:14:53.705: V/Mainwindow.cpp line[0846]    LazyInit()( 969): ^^^^^^^^^^^^^^^^^^^^^^^ time is 13 secs, 935998092 nsecs





离线

#17 2018-04-03 10:50:19

awfans
会员
注册时间: 2018-04-03
已发帖子: 264
积分: 264

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

这个不错, 刚好这几天要做一个 V3s voip要用到。
全志给的cdr代码不知道从哪里开始分析, 没有找到文档。

离线

#18 2020-03-18 20:29:03

吕氏春秋
会员
注册时间: 2020-03-18
已发帖子: 36
积分: 36

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

啊, 不错, mark一下

离线

#19 2020-12-17 09:59:04

whyabc666
封禁
注册时间: 2019-12-12
已发帖子: 378
积分: 365

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

没想到行车记录仪录个视频还要写播放器!还要什么碰撞,什么乱七八糟的事,几个月搞到完美?

离线

#20 2020-12-17 22:47:38

路人甲
会员
注册时间: 2017-09-07
已发帖子: 202
积分: 199.5

Re: 转载一个大神 2014年的行车记录仪项目LOG(感谢为后来者铺路的同行)

发现原来的链接已经打不开了, 晕哥搬运辛苦了.

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn