webrtc-source-android

nativeCreateVideoSource

初始化

PeerConnectionFactory(pc/peerconnectionfactory) 创建PeerConnection方法中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
rtc::scoped_refptr<PeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& configuration,
std::unique_ptr<cricket::PortAllocator> allocator,
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
PeerConnectionObserver* observer) {
RTC_DCHECK(signaling_thread_->IsCurrent());

if (!cert_generator.get()) {
// No certificate generator specified, use the default one.
cert_generator.reset(
new rtc::RTCCertificateGenerator(signaling_thread_, network_thread_));
}

if (!allocator) {
allocator.reset(new cricket::BasicPortAllocator(
default_network_manager_.get(), default_socket_factory_.get()));
}
network_thread_->Invoke<void>(
RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::SetNetworkIgnoreMask,
allocator.get(), options_.network_ignore_mask));

rtc::scoped_refptr<PeerConnection> pc(
new rtc::RefCountedObject<PeerConnection>(this));

if (!pc->Initialize(configuration, std::move(allocator),
std::move(cert_generator), observer)) {
return nullptr;
}
return PeerConnectionProxy::Create(signaling_thread(), pc);
}

构造PeerConnection对象pc,并调用初始化方法Initialize,Initialize中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
ool PeerConnection::Initialize(
const PeerConnectionInterface::RTCConfiguration& configuration,
std::unique_ptr<cricket::PortAllocator> allocator,
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
PeerConnectionObserver* observer) {
TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
if (!allocator) {
LOG(LS_ERROR) << "PeerConnection initialized without a PortAllocator? "
<< "This shouldn't happen if using PeerConnectionFactory.";
return false;
}
if (!observer) {
// TODO(deadbeef): Why do we do this?
LOG(LS_ERROR) << "PeerConnection initialized without a "
<< "PeerConnectionObserver";
return false;
}
observer_ = observer;
port_allocator_ = std::move(allocator);

// The port allocator lives on the network thread and should be initialized
// there.
if (!network_thread()->Invoke<bool>(
RTC_FROM_HERE, rtc::Bind(&PeerConnection::InitializePortAllocator_n,
this, configuration))) {
return false;
}

// Call must be constructed on the worker thread.
factory_->worker_thread()->Invoke<void>(
RTC_FROM_HERE, rtc::Bind(&PeerConnection::CreateCall_w,
this));

session_.reset(new WebRtcSession(
call_.get(), factory_->channel_manager(), configuration.media_config,
event_log_.get(),
factory_->network_thread(),
factory_->worker_thread(), factory_->signaling_thread(),
port_allocator_.get(),
std::unique_ptr<cricket::TransportController>(
factory_->CreateTransportController(
port_allocator_.get(),
configuration.redetermine_role_on_ice_restart)),
#ifdef HAVE_SCTP
std::unique_ptr<cricket::SctpTransportInternalFactory>(
new cricket::SctpTransportFactory(factory_->network_thread()))
#else
nullptr
#endif
));

stats_.reset(new StatsCollector(this));
stats_collector_ = RTCStatsCollector::Create(this);

// Initialize the WebRtcSession. It creates transport channels etc.
if (!session_->Initialize(factory_->options(), std::move(cert_generator),
configuration)) {
return false;
}

// Register PeerConnection as receiver of local ice candidates.
// All the callbacks will be posted to the application from PeerConnection.
session_->RegisterIceObserver(this);
session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
session_->SignalVoiceChannelCreated.connect(
this, &PeerConnection::OnVoiceChannelCreated);
session_->SignalVoiceChannelDestroyed.connect(
this, &PeerConnection::OnVoiceChannelDestroyed);
session_->SignalVideoChannelCreated.connect(
this, &PeerConnection::OnVideoChannelCreated);
session_->SignalVideoChannelDestroyed.connect(
this, &PeerConnection::OnVideoChannelDestroyed);
session_->SignalDataChannelCreated.connect(
this, &PeerConnection::OnDataChannelCreated);
session_->SignalDataChannelDestroyed.connect(
this, &PeerConnection::OnDataChannelDestroyed);
session_->SignalDataChannelOpenMessage.connect(
this, &PeerConnection::OnDataChannelOpenMessage);

configuration_ = configuration;
return true;
}

调用CreateCall_w创建call对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void PeerConnection::CreateCall_w() {
RTC_DCHECK(!call_);

const int kMinBandwidthBps = 30000;
const int kStartBandwidthBps = 300000;
const int kMaxBandwidthBps = 2000000;

webrtc::Call::Config call_config(event_log_.get());
call_config.audio_state =
factory_->channel_manager() ->media_engine()->GetAudioState();
call_config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
call_config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
call_config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;

call_.reset(webrtc::Call::Create(call_config));
}

使用call对象以及PeerConnectionFactory中channel_manager(PeerConnectionFactory中Initialize中创建)构造WebRtcSession对象session_,调用Initialize方法初始化session_,初始化session_槽函数等.session_初始化方法中创建WebRtcSessionDescriptionFactory对象webrtc_session_desc_factory_.

创建Channel

WebRtcSession::SetLocalDescription:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
std::string* err_desc) {
RTC_DCHECK(signaling_thread()->IsCurrent());

// Takes the ownership of |desc| regardless of the result.
std::unique_ptr<SessionDescriptionInterface> desc_temp(desc);

// Validate SDP.
if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) {
return false;
}

// Update the initial_offerer flag if this session is the initial_offerer.
Action action = GetAction(desc->type());
if (state() == STATE_INIT && action == kOffer) {
initial_offerer_ = true;
transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
}

if (action == kAnswer) {
current_local_description_.reset(desc_temp.release());
pending_local_description_.reset(nullptr);
current_remote_description_.reset(pending_remote_description_.release());
} else {
pending_local_description_.reset(desc_temp.release());
}

// Transport and Media channels will be created only when offer is set.
if (action == kOffer && !CreateChannels(local_description()->description())) {
// TODO(mallinath) - Handle CreateChannel failure, as new local description
// is applied. Restore back to old description.
return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc);
}

// Remove unused channels if MediaContentDescription is rejected.
RemoveUnusedChannels(local_description()->description());

if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
return false;
}
if (remote_description()) {
// Now that we have a local description, we can push down remote candidates.
UseCandidatesInSessionDescription(remote_description());
}

pending_ice_restarts_.clear();
if (error() != ERROR_NONE) {
return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
}
return true;
}

action为offer时CreateChannel创建channels:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
const cricket::ContentGroup* bundle_group = nullptr;
if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) {
bundle_group = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
if (!bundle_group) {
LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified";
return false;
}
}
// Creating the media channels and transport proxies.
const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc);
if (voice && !voice->rejected && !voice_channel_) {
if (!CreateVoiceChannel(voice,
GetBundleTransportName(voice, bundle_group))) {
LOG(LS_ERROR) << "Failed to create voice channel.";
return false;
}
}

const cricket::ContentInfo* video = cricket::GetFirstVideoContent(desc);
if (video && !video->rejected && !video_channel_) {
if (!CreateVideoChannel(video,
GetBundleTransportName(video, bundle_group))) {
LOG(LS_ERROR) << "Failed to create video channel.";
return false;
}
}

const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc);
if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected &&
!rtp_data_channel_ && !sctp_transport_) {
if (!CreateDataChannel(data, GetBundleTransportName(data, bundle_group))) {
LOG(LS_ERROR) << "Failed to create data channel.";
return false;
}
}

return true;
}

CreateChannels中创建三个Channel,其中CreateVideoChannel创建视频Channel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
const std::string* bundle_transport) {
bool require_rtcp_mux =
rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;

std::string transport_name =
bundle_transport ? *bundle_transport : content->name;

cricket::DtlsTransportInternal* rtp_dtls_transport =
transport_controller_->CreateDtlsTransport(
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
if (!require_rtcp_mux) {
rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
}

video_channel_.reset(channel_manager_->CreateVideoChannel(
call_, media_config_, rtp_dtls_transport, rtcp_dtls_transport,
transport_controller_->signaling_thread(), content->name, SrtpRequired(),
video_options_));

if (!video_channel_) {
transport_controller_->DestroyDtlsTransport(
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
if (rtcp_dtls_transport) {
transport_controller_->DestroyDtlsTransport(
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
}
return false;
}

video_channel_->SignalRtcpMuxFullyActive.connect(
this, &WebRtcSession::DestroyRtcpTransport_n);
video_channel_->SignalDtlsSrtpSetupFailure.connect(
this, &WebRtcSession::OnDtlsSrtpSetupFailure);

SignalVideoChannelCreated();
video_channel_->SignalSentPacket.connect(this,
&WebRtcSession::OnSentPacket_w);
return true;
}

调用channel_manager的CreateVideoChannel创建BaseChannel基类的cricket::VideoChannel. VideoChannel需要传入VideoMediaChannel作为构造参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//pc/channelmanager.h/cc
VideoChannel* ChannelManager::CreateVideoChannel_w(
webrtc::Call* call,
const cricket::MediaConfig& media_config,
DtlsTransportInternal* rtp_dtls_transport,
DtlsTransportInternal* rtcp_dtls_transport,
rtc::PacketTransportInternal* rtp_packet_transport,
rtc::PacketTransportInternal* rtcp_packet_transport,
rtc::Thread* signaling_thread,
const std::string& content_name,
bool srtp_required,
const VideoOptions& options) {
RTC_DCHECK(initialized_);
RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
RTC_DCHECK(nullptr != call);
VideoMediaChannel* media_channel = media_engine_->CreateVideoChannel(
call, media_config, options);
if (media_channel == NULL) {
return NULL;
}

VideoChannel* video_channel = new VideoChannel(
worker_thread_, network_thread_, signaling_thread, media_channel,
content_name, rtcp_packet_transport == nullptr, srtp_required);
if (!video_channel->Init_w(rtp_dtls_transport, rtcp_dtls_transport,
rtp_packet_transport, rtcp_packet_transport)) {
delete video_channel;
return NULL;
}
video_channels_.push_back(video_channel);
return video_channel;
}

VideoMediaChannel实例media_channel由MediaEngineInterface对象media_engine创建,media_engine由ChannelManager构造方法传入并初始化,ChannelManager由PeerConnectionFactory创建,在PeerConnection初始化方法中,media_engine被创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//pc/peerconnectionfactory.cc
bool PeerConnectionFactory::Initialize() {
RTC_DCHECK(signaling_thread_->IsCurrent());
rtc::InitRandom(rtc::Time32());

default_network_manager_.reset(new rtc::BasicNetworkManager());
if (!default_network_manager_) {
return false;
}

default_socket_factory_.reset(
new rtc::BasicPacketSocketFactory(network_thread_));
if (!default_socket_factory_) {
return false;
}

std::unique_ptr<cricket::MediaEngineInterface> media_engine =
worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>(
RTC_FROM_HERE,
rtc::Bind(&PeerConnectionFactory::CreateMediaEngine_w, this));

channel_manager_.reset(new cricket::ChannelManager(
std::move(media_engine), worker_thread_, network_thread_));

channel_manager_->SetVideoRtxEnabled(true);
if (!channel_manager_->Init()) {
return false;
}

return true;
}

std::unique_ptr<cricket::MediaEngineInterface>
PeerConnectionFactory::CreateMediaEngine_w() {
RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
return std::unique_ptr<cricket::MediaEngineInterface>(
cricket::WebRtcMediaEngineFactory::Create(
default_adm_.get(), audio_encoder_factory_,
audio_decoder_factory_,
video_encoder_factory_.get(), video_decoder_factory_.get(),
external_audio_mixer_));
}

WebRtcMediaEngine2继承自CompositeMediaEngine,CompositeMediaEngine父类MediaEngineInterface有WebRtcVoiceEngine voiceWebRtcVideoEngine2 video两个对象

WebRtcVideoEngine2

WebRtcVideoEngine2定义在media/engine/webrtcvideoengine2.h下,用于创建WebRtcVideoChannel2(定义在同一头文件),WebRtcVideoChannel2定义了WebRtcVideoSendStream与WebRtcVideoReceiveStream两个内部类.

坚持原创技术分享,您的支持将鼓励我继续创作!