美文网首页
音视频流媒体开发【三十八】FFmpeg媒体转换器2-ffmpeg

音视频流媒体开发【三十八】FFmpeg媒体转换器2-ffmpeg

作者: AlanGe | 来源:发表于2023-04-07 16:24 被阅读0次

音视频流媒体开发-目录

02-ffmpeg框架分析

2.1 ffmpeg对应的⽂件

ffmpeg程序涉及的主要⽂件:
  • cmdutils.c:解析命令相关的⼯具函数,不⽤太关注先;
  • ffmpeg_opt.c:负责解析命令⾏输⼊的参数,以-vcodec copy的处理为例,对应了opt_video_codec函数(key-value的结构,-接下来的字符是代表key的开始,key后⾯紧跟着value)
    • 我们重点关注的是解析出来的信息存储在 OptionsContext, ⽐如opt_video_codec函数


    • 然后在处理的时候 open_output_file -> choose_encoder -> new_video_stream ->new_output_stream -> choose_encoder的时候可以获取到对应的编码器到底应该使⽤什么。
  • ffmpeg.c:多媒体⽂件转换器的主体;
  • ffmpeg_cuvid.c:CUDA硬件相关的加速;
  • ffmpeg_filter.c:filter相关;
  • ffmpeg_hw.c:硬件加速相关

2.2 ffmpeg程序框架流程

先忽略含有filter的情况。

  • 解析命令⾏
    • ffmpeg_parse_options 解析命令⾏的函数
    • 对应的命令 const OptionDef options,例如
      { "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_video_codec },
      { "codec", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) },"codec name", "codec" },
  • 打开输⼊⽂件 open_input_file
    • avformat_open_input
    • 分析码流 avformat_find_stream_info
    • 查找对应的编码器
  • 打开输出⽂件 open_output_file
    • avformat_alloc_output_context2 先建⼀个输出⽂件
    • avformat_new_stream 新建⼀个steam
  • 读取输⼊⽂件
    • av_read_frame 读取输⼊⽂件
  • 解码编码
    • 解码:avcodec_send_packet和avcodec_receive_frame
    • 编码:avcodec_send_frame和avcodec_receive_packet
  • 写⼊输出⽂件
    • avformat_write_header写⼊头部
    • av_interleaved_write_frame 交替写⼊packet
    • av_write_trailer 写⼊尾部

2.3 框图分析

transcode()

接下来主要分析transcode():

transcode_init():转码的初始化⼯作。
check_keyboard_interaction():检测键盘操作。⽐如转码的过程中按下“q”键之后,会退出转码,该函数内还有⼀些其他的按键处理,具体看函数实现也是挺简单的。
transcode_step():进⾏转码。
print_report():打印转码信息,输出到屏幕上,⽐如

flush_encoder():输出编码器中剩余的帧。

当中check_keyboard_interaction(),transcode_step(),print_report()三个函数位于⼀个循环之中会不断地运⾏。

transcode_init()

transcode_init()调⽤了以下⼏个重要的函数:

  • init_input_stream():
  • init_output_stream():
  • av_dump_format():在屏幕上打印输出格式信息。注意是输出格式的信息。输⼊格式的信息的打印是在parse_options()函数运⾏过程中调⽤opt_input_file()的时候打印到屏幕上的。
  • init_input_stream():当中调⽤了avcodec_open2()打开编码器。
  • avformat_write_header():写输出⽂件的⽂件头。
transcode_step()

transcode_step()调⽤了例如以下函数:

  • process_input():完毕解码⼯作。
  • transcode_from_filter():未分析。
  • reap_filters():完毕编码⼯作。
  • process_input()流程图如下所示:

get_input_packet():获取⼀帧压缩编码数据,即⼀个AVPacket。当中调⽤了av_read_frame()。
output_packet():解码压缩编码的数据并将之送⾄AVFilterContext。
output_packet()调⽤了例如以下函数:
decode_video():解码⼀帧视频(⼀个AVPacket)。
decode_audio():解码⾳频(并不⼀定是⼀帧,是⼀个AVPacket)。
do_streamcopy():假设不须要⼜⼀次编码的话,则调⽤此函数,⼀般⽤于封装格式之间的转换。速度⽐转码快⾮常多。

  • decode_video()调⽤了例如以下函数:
    avcodec_decode_video2():解码⼀帧视频。
    rate_emu_sleep():要求依照帧率处理数据的时候调⽤。能够避免FFmpeg处理速度过快。经常使⽤于⽹络实时流的处理(RTP/RTMP流的推送)。
    configure_filtergraph():设置AVFilterGraph。
    av_buffersrc_add_frame():将解码后的数据(⼀个AVFrame)送⾄AVFilterContext。

decode_audio()调⽤的函数和decode_video()基本⼀样。唯⼀的不同在于其解码⾳频的函数是avcodec_decode_audio4()

  • reap_filters()
    reap_filters()主要完毕了编码的⼯作。
    其函数调⽤结构例如以下图所看到的。
  • reap_filters()调⽤了例如以下函数
    • av_buffersink_get_buffer_ref():从AVFilterContext中取出⼀帧解码后的数据(结构为AVFilterBufferRef。能够转换为AVFrame)。
    • avfilter_copy_buf_props():AVFilterBufferRef转换为AVFrame。
    • do_audio_out():编码⾳频。
    • do_video_out():编码视频。do_video_out()调⽤了例如以下函数
      • avcodec_encode_video2():编码⼀帧视频。
      • write_frame():写⼊编码后的视频压缩数据。write_frame()调⽤了例如以下函数:
        • av_bitstream_filter_filter():使⽤AVBitStreamFilter的时候。会调⽤此函数进⾏处理。
        • av_interleaved_write_frame():写⼊压缩编码数据。
    • avfilter_unref_buffer():释放资源。
    • do_audio_out()调⽤的函数与do_video_out()基本上⼀样。唯⼀的不同在于视频编码函数avcodec_encode_video2()变成了⾳频编码函数avcodec_encode_audio2()。
exit_program()

exit_program()主要完毕了清理⼯作。调⽤关系例如以下图所看到的。

  • 调⽤了例如以下函数:
    avfilter_graph_free():释放AVFilterGraph。
    avformat_free_context():释放输出⽂件的AVFormatContext。
    av_bitstream_filter_close():关闭AVBitStreamFilter。
    avformat_close_input():关闭输⼊⽂件。

相关文章

网友评论

      本文标题:音视频流媒体开发【三十八】FFmpeg媒体转换器2-ffmpeg

      本文链接:https://www.haomeiwen.com/subject/xsnpddtx.html