新手学习FFmpeg - 调用API完成录屏并进行H.264编码
Screen Record H.264
目前在网络传输视频/音频流都一般会采用H.264进行编码,所以尝试调用FFMPEG API完成Mac录屏功能,同时编码为H.264格式。
在上一篇文章中,通过调用FFmpeg API完成了Mac平台下的录屏功能。在本篇中,对上次的录屏进行优化,将采集到的视频流编码为H.264格式,同时设定FPS和分辨率。
因为是对上次录屏功能的优化,因此处理思路仍然分为三部分:
- 打开输入设备(默认的屏幕设备)
- 初始化输出设备(mp4文件)
- 内容转码
和上次使用的API对比,本次主要增加了涉及到H.264参数设定和H.264 pts/dts 设定的API:
- avcodec_parameters_from_context
- av_rescale_q
初始化输入设备
仍然采用上篇中打开设备的方法:
- 通过
av_find_input_format("avfoundation")获取AVInputFormat。 - 通过
avformat_open_input打开指定的屏幕设备。
然后FFmpeg会返回此设备中的数据流,而FFmpeg处理数据流一般都遵循:确定codec(编码 or 解码)->初始化codec上下文参数->打开codec,这三步。 针对输入设备也就是下面的顺序:
avcodec_find_decoder -> avcodec_alloc_context3 -> avcodec_open2
AVInputFormat会有多个数据流(视频流/音频流),所以首先找到需要处理的流:
codecpar->codec_type == AVMEDIA_TYPE_VIDEO
然后依次调用avcodec_find_decoder,avcodec_alloc_context3和avcodec_open2来初始化codec。
初始化输出设备
最后是将视频数据编码为H.264,并封装到MP4容器中。所以文件名仍设定为out.mp4。
打开输出设备的方法和打开输入设备方法类似:
avcodec_find_encoder -> avcodec_alloc_context3 -> avcodec_open2 -> avformat_write_header
最后的avformat_write_header不是必须的,只有当容器格式要求写Header时才会调用。与上篇中不同的时,明确指定输出CodecContext的编码器类型:
outCodecContext->codec_id = AV_CODEC_ID_H264;
outCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
outCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
outCodecContext->bit_rate = 400000; // 2500000
outCodecContext->width = 1920;
outCodecContext->height = 1080;
同时H.264对pts和dts有要求,因此需要设定timebase:
outCodecContext->time_base = (AVRational) {1, 25};
转码
有了上次的经验之后,处理转码就会稍显简单。 处理流程大致为:
while av_read_frame
|
+---> avcodec_send_packet
|
+----> while avcodec_receive_frame
| 对每一数据帧进行解码
| 通过`sws_scale`进行源帧和目标帧的数据转换
|
+----> avcodec_send_frame
|
+---> while avcodec_receive_packet
|
|
+--->av_interleaved_write_frame (写入到输出设备)
转码最重要的环节就是在avcodec_receive_frame之后的逻辑。 上面说过H.264对pts有要求,因此这里需要对每一帧添加pts值。
int64_t now = av_gettime();
const AVRational codecTimebase = outStream->time_base;
oframe->pts = av_rescale_q(now, (AVRational) {1, 1000000}, codecTimebase);
在最后写入到输出设备之前,仍需要修改pts值:
if (opacket->pts != AV_NOPTS_VALUE)
opacket->pts = av_rescale_q(opacket->pts, outCodecContext->time_base, outStream->time_base);
至此就完成了对视频进行H.264编码的过程。可以看到和上篇处理过程大致相同,唯一不同的地方就是针对H.264编码格式进行了一些特殊处理,除此之外大致流程完全一致。
源码请点击 https://andy-zhangtao.github.io/ffmpeg-examples/
新手学习FFmpeg - 调用API完成录屏并进行H.264编码的更多相关文章
- 新手学习FFmpeg - 调用API完成录屏
调用FFMPEG Device API完成Mac录屏功能. 调用FFMPEG提供的API来完成录屏功能,大致的思路是: 打开输入设备. 打开输出设备. 从输入设备读取视频流,然后经过解码->编码 ...
- 新手学习FFmpeg - 调用API编写实现多次淡入淡出效果的滤镜
前面几篇文章聊了聊FFmpeg的基础知识,我也是接触FFmpeg不久,除了时间处理之外,很多高深(滤镜)操作都没接触到.在学习时间处理的时候,都是通过在ffmpeg目前提供的avfilter基础上面修 ...
- 新手学习FFmpeg - 调用API完成视频的读取和输出
在写了几个avfilter之后,原本以为对ffmpeg应该算是入门了. 结果今天想对一个视频文件进行转码操作,才发现基本的视频读取,输出都搞不定. 痛定思痛,仔细研究了一下ffmpeg提供的examp ...
- 新手学习FFmpeg - 调用API完成两个视频的任意合并
本次尝试在视频A中的任意位置插入视频B. 在上一篇中,我们通过调整PTS可以实现视频的加减速.这只是对同一个视频的调转,本次我们尝试对多个视频进行合并处理. Concat如何运行 ffmpeg提供了一 ...
- 新手学习FFmpeg - 调用API计算关键帧渲染时间点
通过简单的计算来,线上I帧在视频中出现的时间点. 完整代码请参考 https://andy-zhangtao.github.io/ffmpeg-examples/ 名词解释 首先需要明确以下名词概念: ...
- 新手学习FFmpeg - 调用API调整视频局部速率
通过修改setpts代码实现调整视频部分的播放速率. 完整代码可参考: https://andy-zhangtao.github.io/ffmpeg-examples/ 在前面提到了PTS/DTS/T ...
- 新手学习FFmpeg - 通过API实现可控的Filter调用链
虽然通过声明[x][y]avfilter=a=x:b=y;avfilter=xxx的方式可以创建一个可用的Filter调用链,并且在绝大多数场合下这种方式都是靠谱和实用的. 但如果想精细化的管理AVF ...
- 新手学习FFmpeg - 通过API完成filter-complex功能
本篇尝试通过API实现Filter Graph功能. 源码请参看 https://andy-zhangtao.github.io/ffmpeg-examples/ FFmpeg提供了很多实用且强大的滤 ...
- android 调用 screenrecord 实现录屏
首先要说明的是并未实现,本文讲一下自己的思路. adb 使用shell 命令 screenrecord 可录屏. 自己写了个app,通过Process p = Runtime.getRuntime() ...
随机推荐
- Number() 与 parseInt()解析
在 Python 中,将字符串转为整型变量的函数是 int() ,直接使用 int("123")就可以得到 123的输出结果,这样可以比较快速的得到我们想要的结果,在 js 中将 ...
- Floyd—Warshall算法
我们用DP来求解任意两点间的最短路问题 首先定义状态:d[k][i][k]表示使用顶点1~k,i,j的情况下,i到j的最短路径 (d[0][i][j]表示只使用i和j,因此d[0][i][j] = c ...
- TreeSet类的排序
TreeSet支持两种排序方法:自然排序和定制排序.TreeSet默认采用自然排序. 1.自然排序 TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系, ...
- [系列] Go gRPC Hello World
目录 概述 四类服务方法 安装 写个 Hello World 服务 推荐阅读 概述 开始 gRPC 了,这篇文章学习使用 gRPC,输出一个 Hello World. 用 Go 实现 gRPC 的服务 ...
- 模块购物商城和ATM机代码:
http://outofmemory.cn/python/video/let-us-python/ python为程序员服务 快来加入群[python爬虫交流群](群号570070796),发现精彩 ...
- apache bench的简单使用
ApacheBench是 Apache 附带的一个小工具,专门用于 HTTP Server 的benchmark testing,可以同时模拟多个并发请求. 需要针对web做压力测试,所以简单学习了一 ...
- dotnetcore 与 hbase 之二——thrift 客户端的制作
说明 在上一篇文章dotnetcore 与 hbase 之一--hbase 环境准备结束后,我们已经有了 hbase 数据库环境.接下来就可以利用 thrift 生成 c# hbase 客户端了.如果 ...
- WIZnet-io6Library下载及使用
概观 io6Library是一个IPv6集成库,可以轻松集成和管理使用WIZnet硬连线双TCP / IP堆栈控制器(WIZCHIP)产品系列的用户应用程序. io6Library用于管理依赖于用户特 ...
- Mermaid
graph TD; A-->B; A-->C; B-->D; C-->D;
- LeetCode——372. Super Pow
题目链接:https://leetcode.com/problems/super-pow/description/ Your task is to calculate ab mod 1337 wher ...