一、ffmpeg 简介
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。
源码链接:http://ffmpeg.org/download.html#get-sources
编译参数介绍:https://www.jianshu.com/p/137be4377cef
二、简单应用
- 申请内存空间存储媒体流的格式信息,后面很多操作都需要使用到它:AVFormatContext* format_ctx = avformat_alloc_context();
- 加载socket库以及网络加密协议相关的库,为后续使用网络相关提供支持:avformat_network_init();
- 设置设置获取网络摄像头视频流参数:
AVDictionary* options = NULL;
av_dict_set(&options, “buffer_size”, “425984”, 0); //设置缓存大小,1080p可将值调大
av_dict_set(&options, “rtsp_transport”, “udp”, 0); //以udp方式打开,如果以tcp方式打开将udp替换为tcp
av_dict_set(&options, “stimeout”, “2000000”, 0); //设置超时断开连接时间,单位微秒
av_dict_set(&options, “max_delay”, “5000”, 0); //设置最大时延
/* –preset的参数主要调节编码速度和质量的平衡, 有ultrafast、superfast、veryfast、
faster、fast、medium、slow、slower、veryslow、placebo这10个选项,从快到慢。*/
av_dict_set(&options, “preset”, “ultrafast”, 0);
/* –tune的参数主要配合视频类型和视觉优化的参数,或特别的情况。
如果视频的内容符合其中一个可用的调整值又或者有其中需要,则可以使用此选项,否则建议不使用.
zerolatency:零延迟,用在需要非常低的延迟的情况下,比如电视电话会议的编码。*/
av_dict_set(&options, “tune”, “zerolatency”, 0);
还有许多参数可以设置,具体我们可以查看 ffmpeg 源码,比如 avformat_open_input 是结构体 AVFormatContext 提供的 API,在 libavformat/options_table.h 中定义了 AVFormatContext 所有支持的 options 选项
- 读取文件头,获取封装格式相关信息:avformat_open_input(&format_ctx, “rtsp://admin:gti123456@192.168.1.58:554/onvif1″; 不同厂家不同的设备会有相应的url;
解码一段数据,获取流相关信息:avformat_find_stream_info(format_ctx, NULL);
从获取到的视频流信息里面找到图像流和音频流的对应下标:
for (int i = 0; i < format_ctx->nb_streams; i++) {
if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
video_stream_index = i;
else if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
audio_stream_index = i;
}
找到视频H264:
AVCodecParameters *pCodecpar = format_ctx->streams[video_stream_index]->codecpar;
AVCodec *pCodec = avcodec_find_decoder(pCodecpar->codec_id);
独立的解码上下文(最新的ffmpeg去掉了codec,统一使用codecpar。我们可以使用avcodec_parameters_to_context进行替换):
AVCodecContext *vc =vcodec_alloc_context3(pCodec);
avcodec_parameters_to_context(vc, format_ctx->streams[video_stream_index]->codecpar);
初始化一个视音频编解码器的AVCodecContext:avcodec_open2(vc, pCodec, NULL);
申请每一帧视频流的空间:pFrameDec = av_frame_alloc();
从视频流里面读取当前的一个数据包:av_init_packet(&packet); av_read_frame(format_ctx, &packet);
视频解码:avcodec_decode_video2(vc, pFrameDec, &frameFinished, &packet);