8.27ffmpeg+linux摄像头开发记录

1.由于快开学了,将这个摄像头开发的问题记录一下


1.线程问题  将play和init放在两条不同的线程,导致av_read_frame无法访问


2.api接口的新旧问题 ,释放avformat 要用av_format_input_close ,不可以用avformat_free_context,在4.0版本


3.线程的退出问题,如何优雅的退出

旧的接口尽量不要用

4.每次重新打开摄像头,必须先释放之前的参数,否则摄像头会被占用


gop 两个关键帧之间的间隔


i bbb p


b帧


H264编码,把帧分为3种,i帧,p帧 b帧


i帧有完整的图像,而其他两种没有,所以一个视频的i帧越小,视频越小


举例,当年在b站看视频的时候,往回拉,但是不一定完全回到那个地方

很有可能是那个地方没有关键帧


h265对移动端来说性能开销过大


gop_size是什么,是一组连续的画面


帧率:每秒编码进视频文件的帧数目


码率就是比特率,和音频质量有关


DTS 和PTS,前者是解码的时间,后者是显示的时间


avframe:pts,该帧什么时候被显示,avpacket:dts:该包什么时候被解码


2个i 帧形成一个gop_size


帧率:每秒显示25帧


[图片]


所以,时间基简单来说,就是决定了一个帧占用的时间,那么一个帧的duartion应该等于pts乘以time_base.


视频的一个packet就对应了一个帧,音频的一个packet可能就对应了不止一个帧


num_pkt=采样率除以nb_samples


nb_streams->采样数


一般情况下,音频的时间基和采样率成倒数 1/sample_rate


所以pts=n*nbstreams


pts->显示时间戳


dts->解码时间戳

:
决定视频输出时封装方式的函数,写任何一个函数,都会自动匹配相应的封装方式


quantizer


timebase是一个单位,比如说在ffmpeg中是以秒为单位的


如果说是1:1000很容易理解成毫秒,但是如果是1:25呢,这样用常用的单位就无法解释,所以提出了时间基的概念


分数


分母


demux出来的帧的time:是相对于源AVStream的timebase
编码器出来的帧的time:是相对于源AVCodecContext的timebase
mux存入文件等容器的time:是相对于目的AVStream的timebase


这里的Time指的是pts显示时间


只是初始化,需要用av_frame_get_buffer为像素分配内存空间


av_frame_get_buffer的第四个参数的意思是设定内存对齐的对齐数


所以给像素设定内存大小的方式是1.先计算所需内存大小,根据像素类型,款,高,内存 av_frame_get_buffer_size 2.根据计算出来的内存大小对内存进行分配,av_malloc 3.格式化内存空间,av_image_fill_array


cpu的寻址是通过地址总线来访问内存的,32位的cpu一次可以处理4个字节,所以cpu实际寻址的步长就是4个字节,换个说法,就是只对编号是4的倍数的内存地址进行寻址


字长,是cpu一次可以处理的数据的位数


[图片]


[图片]


[图片]


转化成unicode编码


.tolatin1 转化成ascall


编码大概流程


1.初始化各个结构体,给各个结构体分配内存大小,avformat avframe avpacket,


2.找到根据文件格式找到编码器,如H264,设置编码器上下文参数,如gop_SIZE,bitrate,宽高等,找到编码器


3.初始化avframe ,并给单个像素大小分配内存空间,注意(用两个不同的api),设置音视频缓冲区大小,(pframebuf),给它分配大小并格式化av_image_fill_array


简单理解下,av_frame_get_buffer应该是为指针数组avframe->data分配32个字节空间,一个指针占8个字节,之后再给真实的pframebuf分配内存空间,先前已经malloc好了,最后再调用av_image_fill_array对这个pframebuf进行格式化,(底层来说应该是调用了一个av_image_fill_pointer完成指针指向内存块的操作)


到这里,初始化工作就完成了


接着开始编码操作


1,把解码器解出来的yuv420的帧里面的data指针指向的数据分别赋给另外初始化的pframe的数据指针 , 调用avcodec_send_frame,再调用avcodec_recieve_pkt,将拿到的压缩pkt保存到文件里面


[图片]


根据文件格式找到编码器


今天出现的问题,想要实现点一下录制,再点一下,录制完毕,功能

fwrite返回的是元素的个数


在执行过程中更改图标用icon类


通过更改播放器的文件名

音视频同步开发总结

1.解码器和编码器都有一个叫缓冲区的地方 2.av_read_frame()读出来的是av_packet3.读取管道数据的同步问题,可能出现的情况是主线程中的av_fifo_read和采集线程中的av_fifo_write同时对fifo操作时会发生同步问题。所以要用到消费者,生产者模型。4,音视频同步的问题,打时间戳,av_compare_ts比较时间戳,如果音频帧在前面,则至少需要编码一个视频帧,如果视频帧在前面,则至少需要编码多个音视频。5.不是同时上锁时会发生死锁,那么这时候就需要用c++11的方法,进行同时上述上锁。6,最后一定要记得清除编码器的缓冲区。


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值