/* * 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. */ #include "audio/channel_send_frame_transformer_delegate.h" #include #include namespace webrtc { namespace { using IfaceFrameType = TransformableAudioFrameInterface::FrameType; IfaceFrameType InternalFrameTypeToInterfaceFrameType( const AudioFrameType frame_type) { switch (frame_type) { case AudioFrameType::kEmptyFrame: return IfaceFrameType::kEmptyFrame; case AudioFrameType::kAudioFrameSpeech: return IfaceFrameType::kAudioFrameSpeech; case AudioFrameType::kAudioFrameCN: return IfaceFrameType::kAudioFrameCN; } RTC_DCHECK_NOTREACHED(); return IfaceFrameType::kEmptyFrame; } AudioFrameType InterfaceFrameTypeToInternalFrameType( const IfaceFrameType frame_type) { switch (frame_type) { case IfaceFrameType::kEmptyFrame: return AudioFrameType::kEmptyFrame; case IfaceFrameType::kAudioFrameSpeech: return AudioFrameType::kAudioFrameSpeech; case IfaceFrameType::kAudioFrameCN: return AudioFrameType::kAudioFrameCN; } RTC_DCHECK_NOTREACHED(); return AudioFrameType::kEmptyFrame; } class TransformableOutgoingAudioFrame : public TransformableAudioFrameInterface { public: TransformableOutgoingAudioFrame( AudioFrameType frame_type, uint8_t payload_type, uint32_t rtp_timestamp_with_offset, const uint8_t* payload_data, size_t payload_size, absl::optional absolute_capture_timestamp_ms, uint32_t ssrc, std::vector csrcs, const std::string& codec_mime_type) : frame_type_(frame_type), payload_type_(payload_type), rtp_timestamp_with_offset_(rtp_timestamp_with_offset), payload_(payload_data, payload_size), absolute_capture_timestamp_ms_(absolute_capture_timestamp_ms), ssrc_(ssrc), csrcs_(std::move(csrcs)), codec_mime_type_(codec_mime_type) {} ~TransformableOutgoingAudioFrame() override = default; rtc::ArrayView GetData() const override { return payload_; } void SetData(rtc::ArrayView data) override { payload_.SetData(data.data(), data.size()); } uint32_t GetTimestamp() const override { return rtp_timestamp_with_offset_; } uint32_t GetSsrc() const override { return ssrc_; } IfaceFrameType Type() const override { return InternalFrameTypeToInterfaceFrameType(frame_type_); } uint8_t GetPayloadType() const override { return payload_type_; } Direction GetDirection() const override { return Direction::kSender; } std::string GetMimeType() const override { return codec_mime_type_; } rtc::ArrayView GetContributingSources() const override { return csrcs_; } const absl::optional SequenceNumber() const override { return absl::nullopt; } void SetRTPTimestamp(uint32_t rtp_timestamp_with_offset) override { rtp_timestamp_with_offset_ = rtp_timestamp_with_offset; } absl::optional AbsoluteCaptureTimestamp() const override { return absolute_capture_timestamp_ms_; } private: AudioFrameType frame_type_; uint8_t payload_type_; uint32_t rtp_timestamp_with_offset_; rtc::Buffer payload_; absl::optional absolute_capture_timestamp_ms_; uint32_t ssrc_; std::vector csrcs_; std::string codec_mime_type_; }; } // namespace ChannelSendFrameTransformerDelegate::ChannelSendFrameTransformerDelegate( SendFrameCallback send_frame_callback, rtc::scoped_refptr frame_transformer, rtc::TaskQueue* encoder_queue) : send_frame_callback_(send_frame_callback), frame_transformer_(std::move(frame_transformer)), encoder_queue_(encoder_queue) {} void ChannelSendFrameTransformerDelegate::Init() { frame_transformer_->RegisterTransformedFrameCallback( rtc::scoped_refptr(this)); } void ChannelSendFrameTransformerDelegate::Reset() { frame_transformer_->UnregisterTransformedFrameCallback(); frame_transformer_ = nullptr; MutexLock lock(&send_lock_); send_frame_callback_ = SendFrameCallback(); } void ChannelSendFrameTransformerDelegate::Transform( AudioFrameType frame_type, uint8_t payload_type, uint32_t rtp_timestamp, const uint8_t* payload_data, size_t payload_size, int64_t absolute_capture_timestamp_ms, uint32_t ssrc, const std::string& codec_mimetype) { { MutexLock lock(&send_lock_); if (short_circuit_) { send_frame_callback_( frame_type, payload_type, rtp_timestamp, rtc::ArrayView(payload_data, payload_size), absolute_capture_timestamp_ms, /*csrcs=*/{}); return; } } frame_transformer_->Transform( std::make_unique( frame_type, payload_type, rtp_timestamp, payload_data, payload_size, absolute_capture_timestamp_ms, ssrc, /*csrcs=*/std::vector(), codec_mimetype)); } void ChannelSendFrameTransformerDelegate::OnTransformedFrame( std::unique_ptr frame) { MutexLock lock(&send_lock_); if (!send_frame_callback_) return; rtc::scoped_refptr delegate(this); encoder_queue_->PostTask( [delegate = std::move(delegate), frame = std::move(frame)]() mutable { delegate->SendFrame(std::move(frame)); }); } void ChannelSendFrameTransformerDelegate::StartShortCircuiting() { MutexLock lock(&send_lock_); short_circuit_ = true; } void ChannelSendFrameTransformerDelegate::SendFrame( std::unique_ptr frame) const { MutexLock lock(&send_lock_); RTC_DCHECK_RUN_ON(encoder_queue_); if (!send_frame_callback_) return; auto* transformed_frame = static_cast(frame.get()); send_frame_callback_( InterfaceFrameTypeToInternalFrameType(transformed_frame->Type()), transformed_frame->GetPayloadType(), transformed_frame->GetTimestamp(), transformed_frame->GetData(), transformed_frame->AbsoluteCaptureTimestamp() ? *transformed_frame->AbsoluteCaptureTimestamp() : 0, transformed_frame->GetContributingSources()); } std::unique_ptr CloneSenderAudioFrame( TransformableAudioFrameInterface* original) { std::vector csrcs; csrcs.assign(original->GetContributingSources().begin(), original->GetContributingSources().end()); return std::make_unique( InterfaceFrameTypeToInternalFrameType(original->Type()), original->GetPayloadType(), original->GetTimestamp(), original->GetData().data(), original->GetData().size(), original->AbsoluteCaptureTimestamp(), original->GetSsrc(), std::move(csrcs), original->GetMimeType()); } } // namespace webrtc