ffmpeg截取视频流、rtsp录mp4,与海思NVR,内存问题

一、

FFmpeg定时截取rtsp流,60s保存为一个MP4,
我写的ffmpeg的命令为:   ffmpeg -n -rtsp_transport tcp -i rtsp://XXXXXX   -vcodec copy  -acodec copy  -f segment  -segment_time 60 -segment_format mp4 d:\\1\\out%03d.mp4
显示保存的时间都是59s或者60s
但是如果第一个视频是18:01:01--18:02:01     
第二个就是18:02:02--18:03:01
第三个就是18:03:03--18:04:01
。。。
第40个就是18:40:40--18:41:01
。。。
第60个可能就是19:01:01--19:01:01 

越到后面,视频显示60s但是打开就结束了正真可能一秒都不到,我也不知道啥情况

 

 

先丢掉音频试一试

先将整个时间长度的截取下来,自己分段看看

确认下命令是否有问题

用命令的话感觉先整个保存下来, 看看有没有问题

我都很少用ffmepg命令,你可以直接用代码写吗?

ffmpeg -i rtsp://xxxxxx -c copy -map 0 -f segment -segment_time 300 -segment_format mp4 "capture-%03d.mp4"

这个我试过,截取多个后也会出现那个问题
而且不用tcp的丢包多

-segment_atclocktime 1

文件大小正常

想这个.后面3秒就自动跳过去了

用ffplay播放,看看mp4文件有没有什么错误

 

我发现了问题,用 vlc播放是正常的,用windows media player 播放不正常,同一个视频播放的开始时间不一样

我截的图都是从第一秒播放的,但是第一秒就播放时间不一样,少了9s,就导致了后面的9s直接跳过去了

没找到第一个SPS PPS 关键帧,然后直接跳过这个GOP了?

 

二、

rtsp录mp4,现在我录264都是正常的,265录出来不能放

用啥写的mp4文件?你用的库支持265吗?

最新版本的ffmpeg,播放都可以,就是录出来的放不了

不知道h265写mp4头有什么地方不对

直接取的海康摄像头的rtsp

我是用协议接了数据自己处理,我只是用的解码库,存储我是自己写的格式

就是不知道写265有啥区别?

264的直接copy源,windows自带的播放器都能识别,265的啥播放器也放不了,也不算放不了,vlc播放能走秒。就是黑屏

 

 通常是你的SPS,PPS信息没有给对。
 

 

三、

NVR即网络视频录像机,是网络视频监控系统的存储转发部分,其核心功能是视频流的存储与转发。与DVR相比,NVR的功能比较单一,本身不具有模数转换及编码功能,不能独立工作,通常与视频编码器DVS或网络摄像机IPC协同工作,完成视频的录像、存储及转发功能。

相关问题记录:

1、视频预览界面如何画分割线的?

yuv直接画
用vgs
或者用cpu直接操yuv

2、实际项目是如何画的,常规做法,不靠猜。因为上面还要覆盖qt层,我不清楚该画在哪层

两种呀,一种画视频流,一种framebufer

图形层:一般不但有视频,还有UI
UI都是图形层
框也是UI

海思手册推荐vgs画
vgs相当于用显卡加速
没啥麻烦的,播放器都是一帧一帧的画
和pc的播放器没啥区别
贴了图片,在画几条线而已
然后一起显示出来

3、你说的图片就是视频帧?

嗯,解码出来也是yuv
4、要自己贴?不是vpss绑定vo?
也可以不绑定
绑定了,就要用海思里面的discover
reg
等模块,专门画osd
绑定只是mpp在驱动层面帮你画好了,不绑定,就是你自己在应用层画
没啥区别

 

为什么我一个都没听过。reg?discover?
单词打错了
我也不知道怎么拼了
你看下osd那个,有两种叠加osd的方法


5、如果是把框画在视频上。那没视频的通道怎么画框?比如四路,一路有视频,剩下三路没视频。

 

可以画vo上面
实际项目一般都是在FB上
就是UI

图形层
一般都QT搞个框,

 

在视频那留几个框
留几个框是什么意思?
留几个透明的框,
然后,视频层显示在下面就好了

一般解码可以直接绑定到视频层

nvr支持好多视频层,

可以显示好多路

按位置排好就可以了,

然后最上面QT就在显示视频的位置透明
 

机顶盒不需要多路,解码能力要芯片支持

有些芯片可以解码4K 但是不能解码很多路小分辨率的,
nvr一般都可以解码很多路小分辨率,
这个感觉解码库有啥限制,我也不懂
可能资源利用没海思好吧

四、内存问题

频繁调用memcpy会不会带来很大的cpu消耗

优化什么的总是要等到遇到问题再说吧

在设计io读写api时,是直接将数据写入到调用者的缓冲区好(如果数据长度未知会很不灵活),还是先写到api内部的缓冲区再复制到调用者的缓冲区好(中间隔了一层memcpy,担心增加性能负担)
现在遇到的问题是为了避免二次复制,搞得并不是很优雅,只是想把事情做得更优雅一些而已

肯定是一码归一码
怎么能够图这种方便
万一出了叉子怎么查错?
IO只管接受缓存数据就好,其余的事不要他管

我之前设计的api是直接将将调用者的指针来接收解包后的数据,如果它的缓冲区不够,我会将它释放,然后重新分配,感觉很暴力

你如果写入调用者缓冲区,万一调用者缓冲区有个什么加锁解锁的问题
要写的写不进去
整个流程都堵住

就是一个指针而已,不会有什么锁的

一不小心有个什么空指针

类似于ReadStream(uint8_t *buf, int length)
会检测它的指针是否为空

IO肯定有写的过程嘛

好吧,我这个是内存上的io
就是一块数据缓冲区

不管什么地方的IO
是不是要写完了再处理?

少拷贝肯定是好的

然后是不是要处理完了再写?

但还是要考虑整个结构。

这样一来
就是你等我我等你

到性能不够的时候再调整呗,就师出有名了

如果有点问题,很难搞清楚是IO的问题还是处理流程的问题

我现在就是直接拷贝到调用者的缓冲区,只是考虑到它的缓冲区不够大时怎么办,又不想简单粗暴地丢弃数据

如果是我api内部分配一块数据缓冲区,即使发现长度不够,我也可以在内部调整,待所有数据收完后再拷贝到调用者的缓冲区,这样一样就多了一层memcpy了,担心加大性能开销

你这是侥幸心理嘛

什么意思

怎么可能有够的时候

你如果不控制数据源
有协议的
可以界定数据的边界

我是说,你不能指望调整自己的缓冲区大小去解决风险
你应该去想办法控制数据源

目前没有按照协议来,没有这样的风险

你不是担心位置不够大吗?

怎么又没有风险了?

我是担心调用者的缓冲不够大

packet怎么能判断是否包含h264 header?
发现用h264_mp4toannexb处理后的mp4,I帧前是有pps sps的


如果是先缓冲到api本地再一次性拷贝调用者缓冲区,即使它的内存不够,我也能通过错误码来提醒所需的最大缓冲大小了,接下来就是调用者应该处理的事情了

如果是这种API

直接由API负责申请内存不就好了?
让他返回一个结构,缓冲区地址,大小等等信息
没有必要拷贝吧

有考虑过这样的设计方案

不过还是太危险了

哈哈

建议拷贝出去算数

感觉要把事情做得优雅,太难了
我看了live555的内部实现,它在录制rtp包时也是先将数据写入到它自己的缓冲,录完一帧后再将它拷贝到调用者的缓冲区的

这不是优不优雅的问题
这样流程清晰,界限明显

流程清晰,界限明显,已经很优雅了/呲牙

IO和后面的处理程序甚至可以分开开发测试

主要还是看 性能瓶颈在哪里吧。如果copy占比很低无所谓了。
但是如果程序本身就是负责 数据转发,那可能就要考虑考虑了
也就是copy本身是主要任务

我的原则也是性能优先,能不拷贝就不要拷贝,少一分拷贝肯定cpu的负担会低一些,哪怕是微不足道的

微不足道就算了吧

先拷贝到自己的缓存区吧,socket也是先拷贝到自己的缓冲区的

我看libevent好像是直接拷贝最终目的地
但是人家主要任务就是数据转发,那肯定不管好看不好看了
如果在编码中就无所谓了,一帧拷贝时间还没有编码的1%吧
1% 优化到0.5%,牺牲其他就不值得了吧

我一台机器上要并发10几20个客户端的,我就担心并发多了,memcpy会带来性能上的瓶颈
比如加大了cpu的开销导致并发数降低了

要看具体数量咯。如果是十几个同时观看视频的数据
那就的。。
如果只是一般业务性的,十多个还好吧

视频播放客户端来的

算算好像即使10M码率,数据量也不算太大?

现在主流的搞法,IO不宜掺和太多东西
网络不稳,数据异常,丢包,还有对端服务完球什么的
要处理的异常多了去了
能稳定正确的把数据准备好就已经很吃力了
而且因为是与远端协作,调试起来也比较麻烦
就不要操心别的事了
本地计算只要骚操作不太多,调试一下基本都能很快排除故意

把70路视频接到大屏,有开源的软件么?
 

 

 


 

 

 

 

 

 

你可能感兴趣的:(编程)