AddAudioTrack
作者:LanPZzzz
本章我们简单讲述下pc->AddAudioTrack
kAudioLabel = "xxxxxxxx"
rtc::scoped_refptr audio_track(
peer_connection_factory_->CreateAudioTrack(
kAudioLabel, peer_connection_factory_->CreateAudioSource(
cricket::AudioOptions())));
auto result_or_error = peer_connection_->AddTrack(audio_track, {kStreamId});
rtc::scoped_refptr
PeerConnectionFactory::CreateAudioSource(const cricket::AudioOptions& options) {
RTC_DCHECK(signaling_thread_->IsCurrent());
rtc::scoped_refptr source(
LocalAudioSource::Create(&options));
return source;
}
最后创建的是LocalAudioSource(pc\localaudiosource.cc),这是在options 上进行赋值
返回AudioTrackInterface
T = AudioTrackInterface
class AudioTrack : public MediaStreamTrack,
public ObserverInterface
template
class MediaStreamTrack : public Notifier
template
class Notifier : public T
这样层层继承,返回就是AudioTrackInterface,他们太优秀了,整的我代码看着好难受
void AudioTrack::AddSink(AudioTrackSinkInterface* sink) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
if (audio_source_)
audio_source_->AddSink(sink);
}
void AudioTrack::RemoveSink(AudioTrackSinkInterface* sink) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
if (audio_source_)
audio_source_->RemoveSink(sink);
}
AddSink + RemoveSink 都是加入到audio_source中,但是我们的audio_source 是LocalAudioSource,木有用,空方法
AddTrack audio 和 video 都使用同一个,所以在AddVideoTrack的时候这里可能就不讲了
RTCErrorOr> PeerConnection::AddTrack(
rtc::scoped_refptr track,
const std::vector& stream_ids) {
TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
if (!track) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Track is null.");
}
if (!(track->kind() == MediaStreamTrackInterface::kAudioKind ||
track->kind() == MediaStreamTrackInterface::kVideoKind)) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
"Track has invalid kind: " + track->kind());
}
if (IsClosed()) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
"PeerConnection is closed.");
}
1. 查找是否有当前的track
if (FindSenderForTrack(track)) {
LOG_AND_RETURN_ERROR(
RTCErrorType::INVALID_PARAMETER,
"Sender already exists for track " + track->id() + ".");
}
2. 我们使用UnifiedPlan,直接调用AddTrackUnifiedPlan
auto sender_or_error =
(IsUnifiedPlan() ? AddTrackUnifiedPlan(track, stream_ids)
: AddTrackPlanB(track, stream_ids));
if (sender_or_error.ok()) {
3. 回到到observer 上,我们上层没有实现此方法
observer_->OnRenegotiationNeeded();
4. 这里创建每个track的stat report,需要查看下,具体什么使用
stats_->AddTrack(track);
}
return sender_or_error;
}
RTCErrorOr>
PeerConnection::AddTrackUnifiedPlan(
rtc::scoped_refptr track,
const std::vector& stream_ids) {
1. 我们第一次添加都是没有transceiver 的
auto transceiver = FindFirstTransceiverForAddedTrack(track);
if (transceiver) {
RTC_LOG(LS_INFO) << "Reusing an existing "
<< cricket::MediaTypeToString(transceiver->media_type())
<< " transceiver for AddTrack.";
if (transceiver->direction() == RtpTransceiverDirection::kRecvOnly) {
transceiver->internal()->set_direction(
RtpTransceiverDirection::kSendRecv);
} else if (transceiver->direction() == RtpTransceiverDirection::kInactive) {
transceiver->internal()->set_direction(
RtpTransceiverDirection::kSendOnly);
}
transceiver->sender()->SetTrack(track);
transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
} else {
cricket::MediaType media_type =
(track->kind() == MediaStreamTrackInterface::kAudioKind
? cricket::MEDIA_TYPE_AUDIO
: cricket::MEDIA_TYPE_VIDEO);
RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
<< " transceiver in response to a call to AddTrack.";
std::string sender_id = track->id();
// Avoid creating a sender with an existing ID by generating a random ID.
// This can happen if this is the second time AddTrack has created a sender
// for this track.
if (FindSenderById(sender_id)) {
sender_id = rtc::CreateRandomUuid();
}
2. 看下下面的各个函数是什么作用
auto sender = CreateSender(media_type, sender_id, track, stream_ids);
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
transceiver = CreateAndAddTransceiver(sender, receiver);
transceiver->internal()->set_created_by_addtrack(true);
transceiver->internal()->set_direction(RtpTransceiverDirection::kSendRecv);
}
return transceiver->sender();
}
auto strType = cricket::MediaTypeToString(transceiver->media_type());
auto kind = track->kind();
auto hasUsedToSendFlag = transceiver->internal()->has_ever_been_used_to_send();
auto isStop = transceiver->stopped();
rtc::scoped_refptr>
PeerConnection::CreateSender(
cricket::MediaType media_type,
const std::string& id,
rtc::scoped_refptr track,
const std::vector& stream_ids) {
rtc::scoped_refptr> sender;
1. Video send 是 VideoRtpSender, Audio send 是AudioRtpSender,并且会传入stats_
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
RTC_DCHECK(!track ||
(track->kind() == MediaStreamTrackInterface::kAudioKind));
sender = RtpSenderProxyWithInternal::Create(
signaling_thread(),
new AudioRtpSender(worker_thread(), id, stats_.get()));
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
} else {
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
RTC_DCHECK(!track ||
(track->kind() == MediaStreamTrackInterface::kVideoKind));
sender = RtpSenderProxyWithInternal::Create(
signaling_thread(), new VideoRtpSender(worker_thread(), id));
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
}
2. 设置track
bool set_track_succeeded = sender->SetTrack(track);
RTC_DCHECK(set_track_succeeded);
sender->internal()->set_stream_ids(stream_ids);
return sender;
}
PeerConnection::CreateReceiver 没有什么好解释的,AudioRtpReceiver 和 VideoRtpReceiver,入参 receiver_id,stream_ids = std::vectorstd::string({}),有一个默认的stream
auto transceiver = RtpTransceiverProxyWithInternal::Create(
signaling_thread(), new RtpTransceiver(sender, receiver));
transceivers_.push_back(transceiver);
Plan B 有多个 senders 和 receivers 在sdp 中有 m= 片段
// With Plan B SDP, an RtpTransceiver can have any number of senders and
// receivers which map to a=ssrc lines in the m= section.
Unified Plan 只有一个 senders 和 receivers 在sdp 中有 m= 片段,复用
// With Unified Plan SDP, an RtpTransceiver will have exactly one sender and one
// receiver which are encapsulated by the m= section.
本篇讲述了AddAudioTrack,讲述了里面的步骤,包括一些属性