ffmpeg 代码阅读笔记2/2

ffmpeg 代码阅读笔记2/2

调试才是你掌握核心的钥匙,把不懂的东西变成懂. 令你有很多收获.
调试让你搞得懂来龙去脉.
有益的文档帮助你节省时间!
============================================================
0. ffmpeg 主流程
============================================================
ret = ffmpeg_parse_options(argc, argv); //一招完成所有初始化.
if (transcode() < 0) // 一招完成循环处理所有数据.
transcode()退出就结束了.  有点一分为2的思想.

============================================================
乙: transcode() 分析
============================================================
    ret = transcode_init();
    while(1) ret = transcode_step(); // 循环执行

============================================================
一. transcode_init() 分析,
============================================================
1.   ret = init_input_stream(i, error, sizeof(error)); // 重要的是它打开了输入流
   (ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0)
   输出流init 重要项没看见.


============================================================
二. transcode_step() 分析
============================================================
0. choose_output(); //选择ost->st->cur_dts 比较小的流来处理
1. 先跳过filter 部分,目前未使用.
2.    ret = process_input(ist->file_index);
3.    return reap_filters(0);

2.2 process_input
----------------------------------------
 ret = get_input_packet(ifile, &pkt);--> return av_read_frame(f->ctx, *pkt); //获得一个包
 进行了一番时间戳检查,修正等,然后
    process_input_packet ();
     decode_audio()/decode_video();
     decode(); //call avcodec_send_packet(),avcodec_receive_frame()
     //然后
    err = send_frame_to_filters(ist, decoded_frame);

2.3 reap_filters()
----------------------------------------
static int reap_filters(int flush); //从过滤器中获取, 收割filters
 /* Get and encode new output from any of the filtergraphs, without causing activity.*/

    注意以下几点,原来也是如此的简单! 注意区分是底层的handle 还是它自己的数据!!!
    /* Reap all buffers present in the buffer sinks */ 取得所有缓冲接收器中存在的缓冲.
    for (i = 0; i < nb_output_streams; i++) {
        OutputStream *ost = output_streams[i];
        OutputFile    *of = output_files[ost->file_index];
        int ret = 0;

        // ost->filter 只是OutputFilter, 是ffmpeg 自定义的结构(应用)
        // ost->filter->filter 才是是AVFilterContext !!!, 是libav 定义的结构(库)
        // ost->filter->graph 只是FilterGraph, 是ffmpeg 自定义的结构(应用)
        // ost->filter->graph->graph 才是AVFilterGraph !!!, 是libav 定义的结构(库)
        if (!ost->filter || !ost->filter->graph->graph) continue;
        //原来的AVFilterGraph 是空的,它是何时变成非空的,这才是关键! 你需要跟踪调试!才能掌握.
        //参见后述.
        AVFilterContext *filter = ost->filter->filter; // 这才是真正的AVFilterContext
        

        while (1) { // 获取frame
            ret = av_buffersink_get_frame_flags(filter, filtered_frame, AV_BUFFERSINK_FLAG_NO_REQUEST);
            //编码frame, do_audio_out()/do_video_out()
            switch (av_buffersink_get_type(filter)) {
            case AVMEDIA_TYPE_VIDEO:
                do_video_out(of, ost, filtered_frame);
                break;
            case AVMEDIA_TYPE_AUDIO:
                do_audio_out(of, ost, filtered_frame);
                break;
            default:
                // TODO support subtitle filters
                av_assert0(0);
            }
            av_frame_unref(filtered_frame);
        }
    }

    //实际的编码操作, do_audio_out()/do_video_out()
    ret = avcodec_send_frame(enc, frame);
    ret = avcodec_receive_packet(enc, pkt);

----------------------------------------
    AVFilterGraph 配置的实现
----------------------------------------
调用链如下图:
  #0  configure_filtergraph (fg=0x5555558bb200) at ffmpeg_filter.c:991
  #1  ifilter_send_frame (ifilter=0x5555558afd80, frame=0x55555599ddc0) at ffmpeg.c:2238
  #2  send_frame_to_filters (ist=0x555555af3d40, decoded_frame=0x55555599ddc0) at ffmpeg.c:2319
  #3  decode_audio (ist=0x555555af3d40, pkt=0x555555895a00, got_output=0x7fffffffd488, decode_failed=0x7fffffffd490) at ffmpeg.c:2386
  #4  process_input_packet (ist=0x555555af3d40, pkt=0x55555597fe80, no_eof=0) at ffmpeg.c:2671
  #5  process_input (file_index=0) at ffmpeg.c:4610
  #6  transcode_step () at ffmpeg.c:4750
  #7  transcode () at ffmpeg.c:4804
当转换时,以audio 为例,解码audio,向filter 发送,当发现没有配置时,进行一次初始化配置.
配置完filter, 即可向里边添加frame 了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值