webrtc代码相当庞大, 网上的相关资料也很少, 要想搞清楚各模块之间的关系, 最好深入到程序运行时的状态, 需要我们运行webrtc的应用程序, 并开启调试模式; 本文以linux 下的mediasoup-broadcaster-demo调试为例, 简单说明一下webrtc的一些函数调用关系;
- 如何开启webrtc调试(libwebrtc编译)?
$ gn gen out/mybuild-m79 --args='is_debug=true is_component_build=false is_clang=false rtc_include_tests=false rtc_use_h264=true rtc_enable_protobuf=false use_rtti=true use_custom_libcxx=false treat_warnings_as_errors=false use_ozone=true'
把is_debug=true打开即可, 然后编译;
-
mediasoup-broadcaster-demo编译 (开启调试)
-
cgdb运行 (不要用gdb, 还可以用linux eclipse c++调试)
cgdb build/broadcaster
bt 即可查看到调用关系; -
如何查看特定函数的调用关系?
比如我们要查看VideoBroadcaster::OnFrame调用关系, 在这打个断点, 立马会运行到该断点, 然后bt 即可获取到堆栈信息, 即可查看到所有调用关系;
Thread 19 "EncoderQueue" hit Breakpoint 1, webrtc::RtpVideoSender::OnEncodedImage (this=0x7f65340251b0, encoded_image=..., codec_specific_info=0x7f655c174a20, fragmentation=0x0)
at ../../call/rtp_video_sender.cc:461
461 const RTPFragmentationHeader* fragmentation) {
(gdb) bt
0 webrtc::RtpVideoSender::OnEncodedImage (this=0x7f65340251b0, encoded_image=..., codec_specific_info=0x7f655c174a20, fragmentation=0x0) at ../../call/rtp_video_sender.cc:461
1 0x0000561eae01bc9b in webrtc::internal::VideoSendStreamImpl::OnEncodedImage (this=0x7f6534027d60, encoded_image=..., codec_specific_info=0x7f655c174a20, fragmentation=0x0)
at ../../video/video_send_stream_impl.cc:606
2 0x0000561eae29816c in webrtc::VideoStreamEncoder::OnEncodedImage (this=0x7f655c0ba600, encoded_image=..., codec_specific_info=0x7f65498f2210, fragmentation=0x0)
at ../../video/video_stream_encoder.cc:1709
3 0x0000561eadd00d0b in webrtc::LibvpxVp8Encoder::GetEncodedPartitions (this=0x7f655c078a50, input_image=..., retransmission_allowed=true)
at ../../modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc:1182
4 0x0000561eadd00474 in webrtc::LibvpxVp8Encoder::Encode (this=0x7f655c078a50, frame=..., frame_types=0x7f655c0baf80)
at ../../modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc:1096
5 0x0000561eadc88fcd in webrtc::EncoderSimulcastProxy::Encode (this=0x7f655c08fae0, input_image=..., frame_types=0x7f655c0baf80) at ../../media/engine/encoder_simulcast_proxy.cc:56
6 0x0000561eae296484 in webrtc::VideoStreamEncoder::EncodeVideoFrame (this=0x7f655c0ba600, video_frame=..., time_when_posted_us=3408146336) at ../../video/video_stream_encoder.cc:1541
7 0x0000561eae294ed1 in webrtc::VideoStreamEncoder::MaybeEncodeVideoFrame (this=0x7f655c0ba600, video_frame=..., time_when_posted_us=3408146336)
at ../../video/video_stream_encoder.cc:1397
8 0x0000561eae29122f in webrtc::VideoStreamEncoder::<lambda()>::operator()(void) const (__closure=0x7f6544001d98) at ../../video/video_stream_encoder.cc:1113
9 0x0000561eae2a6c50 in webrtc::webrtc_new_closure_impl::ClosureTask<webrtc::VideoStreamEncoder::OnFrame(const webrtc::VideoFrame&)::<lambda()> >::Run(void) (this=0x7f6544001d90)
at ../../rtc_base/task_utils/to_queued_task.h:31
10 0x0000561eadc50004 in webrtc::(anonymous namespace)::TaskQueueLibevent::OnWakeup (socket=51, flags=2, context=0x7f655c07f850) at ../../rtc_base/task_queue_libevent.cc:282
11 0x0000561eadc531a6 in event_process_active (base=0x7f655c077eb0) at ../../base/third_party/libevent/event.c:381
12 0x0000561eadc534cd in event_base_loop (base=0x7f655c077eb0, flags=0) at ../../base/third_party/libevent/event.c:521
13 0x0000561eadc4fca9 in webrtc::(anonymous namespace)::TaskQueueLibevent::ThreadMain (context=0x7f655c07f850) at ../../rtc_base/task_queue_libevent.cc:253
14 0x0000561eada0e75f in rtc::PlatformThread::Run (this=0x7f655c07f8f0) at ../../rtc_base/platform_thread.cc:130
15 0x0000561eada0dee8 in rtc::PlatformThread::StartThread (param=0x7f655c07f8f0) at ../../rtc_base/platform_thread.cc:67
16 0x00007f65723b26db in start_thread (arg=0x7f65498f4700) at pthread_create.c:463
17 0x00007f657179c88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
接下来, 你可以查看任意你想查看的函数的调用关系, 是不是很爽!但前提是这个函数被调用了, 不然也不会有堆栈信息!
cgdb 和 eclipse c++ 都是很好的调试工具, eclipse c++ 调试的过程中不容易打断点到特定函数, 要找; cgdb 打断点太方便, bt 函数名即可, 如果有同名函数, 则都会被打上断点, 功能太强大; 本人一直喜欢图形化的界面, 但是目前觉得cgdb; 更好用;
网友评论