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

简介: 双路录像利用静态变量做多对象之间简单写互斥       笔者目前在研的项目是基于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的时候先判断一下是否有任务写,如果有就把阀值临时调大一点,缓存会继续接受编码数据,得到达到新阀值的时候,先前的那个写任务早就完成了。这样就可以岔开这个写动作,这个修改从总的来说,改善还是蛮多的。另外还得考虑一下,下次万一还是没写完的情况,也得做一个强制启动写,不能一直这样缓存下去。考虑问题还是尽量要闭环思维。

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

 

 

目录
相关文章
|
27天前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
36 4
|
1月前
|
存储 安全 Java
JVM锁的膨胀过程与锁内存变化解析
在Java虚拟机(JVM)中,锁机制是确保多线程环境下数据一致性和线程安全的重要手段。随着线程对共享资源的竞争程度不同,JVM中的锁会经历从低级到高级的膨胀过程,以适应不同的并发场景。本文将深入探讨JVM锁的膨胀过程,以及锁在内存中的变化。
35 1
|
4月前
|
存储 缓存 算法
(五)JVM成神路之对象内存布局、分配过程、从生至死历程、强弱软虚引用全面剖析
在上篇文章中曾详细谈到了JVM的内存区域,其中也曾提及了:Java程序运行过程中,绝大部分创建的对象都会被分配在堆空间内。而本篇文章则会站在对象实例的角度,阐述一个Java对象从生到死的历程、Java对象在内存中的布局以及对象引用类型。
122 8
|
2月前
|
存储 程序员 C语言
堆和栈之间有什么区别
【9月更文挑战第1天】堆和栈之间有什么区别
578 0
|
3月前
|
Java 数据库连接 数据库
|
存储
【线程概念和线程控制】(二)
【线程概念和线程控制】(二)
64 0
|
传感器 编译器
__weak关键字:程序模块相互独立的大杀器
__weak关键字:程序模块相互独立的大杀器
76 0
|
消息中间件 Cloud Native Java
线程同步模式之保护性暂停
保护性暂停是一种同步模式,用于保护共享资源的完整性。在多线程或多进程环境中,如果多个线程或进程同时访问共享资源,可能会导致数据不一致或者竞态条件等问题
163 0
对象的创建过程、DCL与Volatile之间的纠葛
对象的创建过程、DCL与Volatile之间的纠葛
对象的创建过程、DCL与Volatile之间的纠葛
|
存储 缓存 算法
怎么理解Java内存区域
怎么理解Java内存区域
123 0
怎么理解Java内存区域