ffmpeg 1.0 filter的picref流程分析

2014 10 19
ffmpeg 1.0 filter的picref流程分析:

 

ffmpeg -y -i vga.3gp -vcodec libx264 -an -strict -2 merge.3gp
该命令产生4个filter:buffer->null->format->ffbuffersink.

分析:
解码一帧数据后会调用av_buffersrc_add_ref来将其推入filter系统进行处理,
sink_buffer.c文件里 request_frame函数调用ff_start_frame 后到递归结束,堆栈如下:
 testffmpeg.exe!default_start_frame(AVFilterLink * inlink, AVFilterBufferRef * picref)  行 215 C
  testffmpeg.exe!ff_start_frame(AVFilterLink * link, AVFilterBufferRef * picref)  行 306 + 0x10 字节 C
  testffmpeg.exe!ff_null_start_frame(AVFilterLink * link, AVFilterBufferRef * picref)  行 169 + 0x15 字节 C
  testffmpeg.exe!ff_start_frame(AVFilterLink * link, AVFilterBufferRef * picref)  行 306 + 0x10 字节 C
  testffmpeg.exe!ff_null_start_frame(AVFilterLink * link, AVFilterBufferRef * picref)  行 169 + 0x15 字节 C
  testffmpeg.exe!ff_start_frame(AVFilterLink * link, AVFilterBufferRef * picref)  行 306 + 0x10 字节 C
  testffmpeg.exe!request_frame(AVFilterLink * link)  行 432 + 0xd 字节 C
  testffmpeg.exe!av_buffersrc_add_ref(AVFilterContext * s, AVFilterBufferRef * buf, int flags)  行 165 + 0x16 字节 C
  testffmpeg.exe!decode_video(InputStream * ist, AVPacket * pkt, int * got_output)  行 1766 + 0x20 字节 C
  testffmpeg.exe!output_packet(InputStream * ist, const AVPacket * pkt)  行 1883 + 0x18 字节 C
  testffmpeg.exe!process_input(int file_index)  行 3022 + 0xd 字节 C
  testffmpeg.exe!transcode_step()  行 3132 + 0xb 字节 C
  testffmpeg.exe!transcode()  行 3189 + 0x5 字节 C
  testffmpeg.exe!wmain(int argc, char * * argv)  行 329 + 0xd 字节 C++
  testffmpeg.exe!__tmainCRTStartup()  行 552 + 0x19 字节 C
  testffmpeg.exe!wmainCRTStartup()  行 371 C
在该过程中,分别对buffer/null/format的outlink->cur_buf进行赋值。其中buffer的outlink->cur_buf
是由decode_video调用avfilter_get_video_buffer_ref_from_arrays来获取
并作为av_buffersrc_add_ref函数的参数传入的。而null/format的outlink->cur_buf则是由
ff_null_start_frame函数调用avfilter_ref_buffer来产生的一个新的reference(通过
ff_start_frame(link->dst->outputs[0], buf_out)来传递给下一个filter的outlink->cur_buf)
。产生一个新的 reference估计是为了下一个filter处理方便,不影响上一个filtrer.

sink_buffer.c文件里request_frame函数调用 ff_end_frame 后到递归结束,堆栈如下:
  testffmpeg.exe!end_frame(AVFilterLink * inlink)  行 134 C
  testffmpeg.exe!ff_end_frame(AVFilterLink * link)  行 344 + 0x9 字节 C
  testffmpeg.exe!ff_null_end_frame(AVFilterLink * link)  行 320 + 0x11 字节 C
  testffmpeg.exe!ff_end_frame(AVFilterLink * link)  行 344 + 0x9 字节 C
  testffmpeg.exe!ff_null_end_frame(AVFilterLink * link)  行 320 + 0x11 字节 C
  testffmpeg.exe!ff_end_frame(AVFilterLink * link)  行 344 + 0x9 字节 C
  testffmpeg.exe!request_frame(AVFilterLink * link)  行 434 + 0x9 字节 C
  testffmpeg.exe!av_buffersrc_add_ref(AVFilterContext * s, AVFilterBufferRef * buf, int flags)  行 165 + 0x16 字节 C
  testffmpeg.exe!decode_video(InputStream * ist, AVPacket * pkt, int * got_output)  行 1766 + 0x20 字节 C
  testffmpeg.exe!output_packet(InputStream * ist, const AVPacket * pkt)  行 1883 + 0x18 字节 C
  testffmpeg.exe!process_input(int file_index)  行 3022 + 0xd 字节 C
  testffmpeg.exe!transcode_step()  行 3132 + 0xb 字节 C
  testffmpeg.exe!transcode()  行 3189 + 0x5 字节 C
  testffmpeg.exe!wmain(int argc, char * * argv)  行 329 + 0xd 字节 C++
  testffmpeg.exe!__tmainCRTStartup()  行 552 + 0x19 字节 C
  testffmpeg.exe!wmainCRTStartup()  行 371 C
  
在sink_buffer文件的end_frame 函数里,inlink->cur_buf被add_buffer_ref,并将inlink->cur_buf = NULL,
所以format的outlink->cur_buf不会被释放。
接下来调用clear_link(link)将null和format的outlink->cur_buf释放(由于是递归,所以顺序相反)

综上,通过ff_start_frame/ff_end_frame的配对处理,已经将picref成功推入了sink_buffer的fifo里。
传入的以及null产生的picref被unref了。最后在reap_filters函数里调用av_buffersink_get_buffer_ref进行编码处理
并调用avfilter_unref_buffer最终将其释放。

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章