/* * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
AudioMixer::Source::AudioFrameInfo AudioIngress::GetAudioFrameWithInfo( int sampling_rate,
AudioFrame* audio_frame) {
audio_frame->sample_rate_hz_ = sampling_rate;
// Get 10ms raw PCM data from the ACM. bool muted = false;
{
MutexLock lock(&lock_); if ((neteq_->GetAudio(audio_frame, &muted) != NetEq::kOK) ||
!resampler_helper_.MaybeResample(sampling_rate, audio_frame)) {
RTC_DLOG(LS_ERROR) << "GetAudio() failed!"; // In all likelihood, the audio in this frame is garbage. We return an // error so that the audio mixer module doesn't add it to the mix. As // a result, it won't be played out and the actions skipped here are // irrelevant. return AudioMixer::Source::AudioFrameInfo::kError;
}
}
if (muted) {
AudioFrameOperations::Mute(audio_frame);
}
// If caller invoked StopPlay(), then mute the frame. if (!playing_) {
AudioFrameOperations::Mute(audio_frame);
muted = true;
}
// Set first rtp timestamp with first audio frame with valid timestamp. if (first_rtp_timestamp_ < 0 && audio_frame->timestamp_ != 0) {
first_rtp_timestamp_ = audio_frame->timestamp_;
}
if (first_rtp_timestamp_ >= 0) { // Compute elapsed and NTP times.
int64_t unwrap_timestamp;
{
MutexLock lock(&lock_);
unwrap_timestamp =
timestamp_wrap_handler_.Unwrap(audio_frame->timestamp_);
audio_frame->ntp_time_ms_ =
ntp_estimator_.Estimate(audio_frame->timestamp_);
} // For clock rate, default to the playout sampling rate if we haven't // received any packets yet.
std::optional<NetEq::DecoderFormat> decoder =
neteq_->GetCurrentDecoderFormat(); int clock_rate = decoder ? decoder->sdp_format.clockrate_hz
: neteq_->last_output_sample_rate_hz();
RTC_DCHECK_GT(clock_rate, 0);
audio_frame->elapsed_time_ms_ =
(unwrap_timestamp - first_rtp_timestamp_) / (clock_rate / 1000);
}
// Set payload type's sampling rate before we feed it into ReceiveStatistics.
{
MutexLock lock(&lock_); constauto& it =
receive_codec_info_.find(rtp_packet_received.PayloadType()); // If sampling rate info is not available in our received codec set, it // would mean that remote media endpoint is sending incorrect payload id // which can't be processed correctly especially on payload type id in // dynamic range. if (it == receive_codec_info_.end()) {
RTC_DLOG(LS_WARNING) << "Unexpected payload id received: "
<< rtp_packet_received.PayloadType(); return;
}
rtp_packet_received.set_payload_type_frequency(it->second);
}
// Track current remote SSRC. if (rtp_packet_received.Ssrc() != remote_ssrc_) {
rtp_rtcp_->SetRemoteSSRC(rtp_packet_received.Ssrc());
remote_ssrc_.store(rtp_packet_received.Ssrc());
}
// Push the incoming payload (parsed and ready for decoding) into the ACM. if (data_view.empty()) {
neteq_->InsertEmptyPacket(header);
} elseif (neteq_->InsertPacket(header, data_view,
env_.clock().CurrentTime()) < 0) {
RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to " "insert packet into NetEq";
}
}
// If we don't have remote ssrc at this point, it's likely that remote // endpoint is receive-only or it could have restarted the media. if (sender_ssrc != remote_ssrc_) {
rtp_rtcp_->SetRemoteSSRC(sender_ssrc);
remote_ssrc_.store(sender_ssrc);
}
}
// Deliver RTCP packet to RTP/RTCP module for parsing and processing.
rtp_rtcp_->IncomingRtcpPacket(rtcp_packet);
std::optional<TimeDelta> rtt = rtp_rtcp_->LastRtt(); if (!rtt.has_value()) { // Waiting for valid RTT. return;
}
std::optional<RtpRtcpInterface::SenderReportStats> last_sr =
rtp_rtcp_->GetSenderReportStats(); if (!last_sr.has_value()) { // Waiting for RTCP. return;
}
// Get clockrate for current decoder ahead of jitter calculation. auto decoder = neteq_->GetCurrentDecoderFormat(); const uint32_t clockrate_hz = decoder ? decoder->sdp_format.clockrate_hz : 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.