1.前沿
接触ffmpeg2年多,系统使用大概半年左右。ffmpeg命令行方式作为“本地文件”处理足够,但要更加精准的控制还是需要借用SDK的方式,好在ffmpeg的example中提供了大量的简单例子。好了废话不多说,开始干活。
ffmpeg版本3.2
2.主体结构分析
简单记录讲解比较重要的函数
main:主函数入口
|--*_register_all:注册各种模块(ffmpeg驱动模块化思维的最佳体现);
|--avformat_network_init:初始化网络环境
|--ffmpeg_parse_options:<1>解析并设置命令行的输入参数;<2>打开输入输出“文件”;<3>初始化complex filters;
|--transcode:转码/流重封装入口
|--transcode_init:初始化输入输出的codec;
|--init_input_stream
|--avcodec_open2:打开解码器
|--init_output_stream
|--1.0.编码
|--1.1.init_output_stream_encode:设置编码参数的函数,该函数具有很强的参考意义
|--1.2.avcodec_open2:打开编码器
|--1.3.avcodec_parameters_from_context
|--1.4.avcodec_copy_context
|--2.0.重封装
|--2.1.init_output_stream_streamcopy:重封装函数
|--2.2.avcodec_parameters_to_context
|--init_output_bsfs:初始化bsfs(bsfs相关函数接口有新的变化,可以参考更新
|--transcode_step
|--configure_filtergraph:初始化simple filters,包括构建graph
|--transcode_from_filter:
|--avfilter_graph_request_oldest
|--reap_filters(0)
|--av_buffersink_get_frame_flags (AV_BUFFERSINK_FLAG_NO_REQUEST)
|--do_video_out
|--process_input:转码重要步骤
|--get_input_packet:获取解码帧数据
|--av_read_frame:读取一帧数据
|--process_input_packet
|--decode_video
|--decode:(avcodec_send_packet/avcodec_receive_frame):解码关键函数,新的接口
|--av_frame_get_best_effort_timestamp
|--send_frame_to_filters:将解码帧送往graph入口
|--ifilter_send_frame
|--reap_filters(1)
|--av_buffersrc_add_frame_flags (AV_BUFFERSRC_FLAG_PUSH)
|--reap_filters(0):获取帧并封装输出
HAVE_PTHREADS:将为对读输入流单独创建线程,读取的帧数据放入队列;当解码需要数据时,再从队列中取出数据;
3.reap_filters分析
reap_filters
|--av_buffersink_get_frame_flags (AV_BUFFERSINK_FLAG_NO_REQUEST):从graph输出口获取filter数据
|--do_video_out
|--编码:(avcodec_send_frame/avcodec_receive_packet) :编码帧
|--av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase);
|--output_packet
|--bitstream filters:(av_bsf_send_packet/av_bsf_receive_packet):bsfs处理
|--write_packet:封装发送
|--av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base);
|--av_interleaved_write_frame(s, pkt);
4.关于ffmpeg例子的一些坑
1.编码后的fps和tbc,总是源的两倍?
2.输出为mpegts时,且设置muxrate,阻塞?
3.当流出现丢包时,会卡住?
4.多线程使用,出现段错误?
5.当不使用muxrate时,pat/pmt/pcr间隔严重失准?
6.如何偏移pts和dts?