双路录像利用静态变量做多对象之间简单写互斥

简介: 双路录像利用静态变量做多对象之间简单写互斥       笔者目前在研的项目是基于android6.0的智能后视镜产品,目前存在前视录像跟后视录像的功能,存储的文件路径都是保持到外部的同一张SD卡上的。

双路录像利用静态变量做多对象之间简单写互斥

       笔者目前在研的项目是基于android6.0的智能后视镜产品,目前存在前视录像跟后视录像的功能,存储的文件路径都是保持到外部的同一张SD卡上的。我们都有一个这样的经验:比如往SD卡拷文件,比如2个文件都是50M,先拷贝第一个50M文件完成后,再拷贝另外一个50M的文件,这样拷贝这2个总共100M文件花费的时间比会先拷贝一个50M文件,在还没有完成拷贝第一个文件的时候就复制拷贝第二个50M的文件到SD卡上等它完成拷贝花费的总时间要少。:

/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/edsam49原创,转载请注明出处,谢谢!
/*****************************************************************************************************/

       因为都有这样的体验,确实两个任务在操作同一个卡的时候,总是需要一些协调管理的开销,还会造成写不连续分配簇的问题;那跟我们双路录像有什么关系呢,理论上也是一样的,两个任务会操作同一个SD卡,从效率上看,把两个任务协调成一个任务肯定是更好的效率、性能。

两个不同的任务实际上是两个不同的对象,但是又是同一个类的,因为都要封装成一样的视频格式,因此写卡就在封装格式完成后的接收对象里面。可能很多人会说,在这两个任务里面有很多方法来把他们互相开,理论上确实是这样。做二次开发,很多时候还得看原厂提供的大框架,改动太大出问题了原厂还不一定支持你,另外真改动太大了耗费的人力物力也大,我们想以较小的代价来实现这个功能。

       笔者前视录像的码率固定在6M,后视固定在2.2M左右,因此按照编码缓存达到2M阀值后一次写入2M,效率确实会好很多,但是难免会出现两个任务同时写的时候。通过分析,前视的每一次写之间的间隔在2.6~2.8秒之间,后视的在7秒左右,这样留给我们的操作空间就是很大的。

首先我们来看一个打印,笔者加了一个静态变量【cun】,打印如下

09-05 10:13:14.757 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:17.146 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 71,fd = 83
09-05 10:13:17.285 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:20.045 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 72,fd = 83
09-05 10:13:20.176 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:20.387 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 73,fd = 65
09-05 10:13:20.523 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=65
09-05 10:13:22.694 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 74,fd = 83
09-05 10:13:22.839 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:25.453 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 75,fd = 83
09-05 10:13:25.583 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:27.631 D/V4L2CameraDevice( 1677): Mic TVIN framerate = 29fps@720x480 
09-05 10:13:28.045 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 76,fd = 65
09-05 10:13:28.178 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=65
09-05 10:13:28.218 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 77,fd = 83
09-05 10:13:28.368 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:30.859 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 78,fd = 83
09-05 10:13:31.030 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:33.700 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 79,fd = 83
09-05 10:13:33.836 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:35.495 D/MvwPcmRecordListener( 4465): ---> length=8000,ret = 0
09-05 10:13:35.502 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 80,fd = 65
09-05 10:13:35.646 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=65
09-05 10:13:36.419 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 81,fd = 83
09-05 10:13:36.551 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:38.976 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 82,fd = 83
09-05 10:13:39.127 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:41.856 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 83,fd = 83
09-05 10:13:41.996 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:43.222 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 84,fd = 65
09-05 10:13:43.363 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=65
09-05 10:13:43.993 D/V4L2CameraDevice( 1677): Mic CSI framerate = 24fps@1280x720 
09-05 10:13:44.626 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 85,fd = 83
09-05 10:13:44.758 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:47.304 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 86,fd = 83
09-05 10:13:47.445 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:50.021 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 87,fd = 83
09-05 10:13:50.157 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:50.846 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 88,fd = 65
09-05 10:13:51.013 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=65
09-05 10:13:52.704 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 89,fd = 83
09-05 10:13:52.840 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:55.544 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 90,fd = 83
09-05 10:13:55.681 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:58.223 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 91,fd = 83
09-05 10:13:58.357 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=83
09-05 10:13:58.461 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 92,fd = 65
09-05 10:13:58.602 D/MPEG2TSWriter( 1677): 2##2writeAwCache sfd=65
09-05 10:14:00.822 D/MPEG2TSWriter( 1677): ####judgCouldWrite 1 flag =49,cun = 93,fd = 83

        从打印上,存在两个fd,一个是65一个是83,这是两个不同的文件句柄,跟随两个对象里打印出的cun变量确实是线性增长的。那么机会就来了,可以使用这个静态变量来做简单互斥。

static int writingNow =0;

else if((writingNow != 0) && (0 == mForceWrite)){
      /*other process has write, so need delay a short time*/
	   ALOGD("1## writeAwCache sfd=%d, writingNow=%d", sfd, writingNow);
       memcpy(mAwCache.mCacheData + mAwCache.mValidCacheSize, (uint8_t *)write_data, needWriteSize);
       mAwCache.mValidCacheSize += needWriteSize;
	   mAwCache.mCacheSize = mAwCache.mCacheSize + 200*1024;
	   mForceWrite = 1;
	}

     大概思路是这样的,在写之前都判断一下【cun】是不是为0,如果是0,那就说明还没有人写,那就可以立马先把【cun】置一,然后再写,因为笔者使用的是class10的卡,因此2M的写入基本在200ms之内就解决了;因此笔者就定了一个能兼容两个人任务的时间缓冲,也就是保障一个任务完全写完成后才开始另外一个写任务。考虑到了这一点,实施起来就简单了,笔者想得比较简单一点,就是在写阀值稍微调大一点,在将触发老阀值2M的时候先判断一下是否有任务写,如果有就把阀值临时调大一点,缓存会继续接受编码数据,得到达到新阀值的时候,先前的那个写任务早就完成了。这样就可以岔开这个写动作,这个修改从总的来说,改善还是蛮多的。另外还得考虑一下,下次万一还是没写完的情况,也得做一个强制启动写,不能一直这样缓存下去。考虑问题还是尽量要闭环思维。

       这个思路套路不深,浅显易懂。笔者通过批量机器试验,证明还是行之有效的。

 

 

目录
相关文章
|
3月前
|
存储 程序员 C语言
堆和栈之间有什么区别
【9月更文挑战第1天】堆和栈之间有什么区别
860 0
【函数栈帧的创建和销毁】 -- 神仙级别底层原理,你学会了吗?(2)
1.函数的调用方式 相信你对调用函数一点都不陌生,但是在调用函数的过程中,却存在着很多你无法见到的东西,这是底层信息,想要理解透彻,就得深入底层去观察。 本文以一个最简单的加法函数为例,深入讲解内存空间中的每一条指令。
【函数栈帧的创建和销毁】 -- 神仙级别底层原理,你学会了吗?(1)
1.函数的调用方式 相信你对调用函数一点都不陌生,但是在调用函数的过程中,却存在着很多你无法见到的东西,这是底层信息,想要理解透彻,就得深入底层去观察。 本文以一个最简单的加法函数为例,深入讲解内存空间中的每一条指令。
|
存储 NoSQL Linux
Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号
本篇文章重点详细地写了Linux进程信号的知识点:Linux进程信号的概念、信号产生的方式、信号传递和信号阻塞的原理、信号捕捉的方式、内核态、用户态、可重入函数的概念、volatile理解等等。
Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号
对象的创建过程、DCL与Volatile之间的纠葛
对象的创建过程、DCL与Volatile之间的纠葛
对象的创建过程、DCL与Volatile之间的纠葛
|
存储 缓存 算法
怎么理解Java内存区域
怎么理解Java内存区域
132 0
怎么理解Java内存区域
ReadWriteLock 读写之间互斥吗?我竟然答不上来。。
ReadWriteLock 读写之间互斥吗?我竟然答不上来。。
108 0
ReadWriteLock 读写之间互斥吗?我竟然答不上来。。
J3
|
存储 缓存 安全
聊聊虚拟机的垃圾回收算法细节问题-根节点枚举、安全点、安全区、记忆集与卡表、写屏障、并发可达性分析中的三色标记法
聊聊虚拟机的垃圾回收算法细节问题-根节点枚举、安全点、安全区、记忆集与卡表、写屏障、并发可达性分析中的三色标记法
J3
329 0
聊聊虚拟机的垃圾回收算法细节问题-根节点枚举、安全点、安全区、记忆集与卡表、写屏障、并发可达性分析中的三色标记法
|
安全 Java 编译器
C++中以独立语句将new对象置入智能指针
C++中以独立语句将new对象置入智能指针
196 0
|
存储 缓存 Java
Java对象引用四个级别(强、软、弱、虚)
最近,高级Java技术栈微信群中,有一些猿友在讨论JVM中对象的周期问题,有谈到引用的级别,现在为大家做个总结吧,虽然大多数公司并没有意识或者用到这些引用,但了解这些基本概念对熟悉整个垃圾回收机制和面试是非常有帮助的。
140 0
Java对象引用四个级别(强、软、弱、虚)