blob: 18f46d1d094208f240a992aaea5277eb47a2fe09 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h"
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/webrtc/api/frame_transformer_interface.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
namespace blink {
namespace {
// This delegate class exists to work around the fact that
// RTCEncodedAudioStreamTransformer cannot derive from rtc::RefCountedObject
// and post tasks referencing itself as an rtc::scoped_refptr. Instead,
// RTCEncodedAudioStreamTransformer creates a delegate using
// rtc::RefCountedObject and posts tasks referencing the delegate, which invokes
// the RTCEncodedAudioStreamTransformer via callbacks.
class RTCEncodedAudioStreamTransformerDelegate
: public webrtc::FrameTransformerInterface {
public:
RTCEncodedAudioStreamTransformerDelegate(
const base::WeakPtr<RTCEncodedAudioStreamTransformer>& transformer,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
: transformer_(transformer),
main_task_runner_(std::move(main_task_runner)) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
}
// webrtc::FrameTransformerInterface
void RegisterTransformedFrameCallback(
rtc::scoped_refptr<webrtc::TransformedFrameCallback>
send_frame_to_sink_callback) override {
PostCrossThreadTask(
*main_task_runner_, FROM_HERE,
CrossThreadBindOnce(
&RTCEncodedAudioStreamTransformer::RegisterTransformedFrameCallback,
transformer_, std::move(send_frame_to_sink_callback)));
}
void UnregisterTransformedFrameCallback() override {
PostCrossThreadTask(
*main_task_runner_, FROM_HERE,
CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::
UnregisterTransformedFrameCallback,
transformer_));
}
void Transform(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) override {
auto audio_frame = base::WrapUnique(
static_cast<webrtc::TransformableFrameInterface*>(frame.release()));
PostCrossThreadTask(
*main_task_runner_, FROM_HERE,
CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::TransformFrame,
transformer_, std::move(audio_frame)));
}
private:
base::WeakPtr<RTCEncodedAudioStreamTransformer> transformer_;
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
};
} // namespace
RTCEncodedAudioStreamTransformer::RTCEncodedAudioStreamTransformer(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
DCHECK(main_task_runner->BelongsToCurrentThread());
delegate_ =
new rtc::RefCountedObject<RTCEncodedAudioStreamTransformerDelegate>(
weak_factory_.GetWeakPtr(), std::move(main_task_runner));
}
void RTCEncodedAudioStreamTransformer::RegisterTransformedFrameCallback(
rtc::scoped_refptr<webrtc::TransformedFrameCallback> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
send_frame_to_sink_cb_ = callback;
}
void RTCEncodedAudioStreamTransformer::UnregisterTransformedFrameCallback() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
send_frame_to_sink_cb_ = nullptr;
}
void RTCEncodedAudioStreamTransformer::TransformFrame(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// If no transformer callback has been set, drop the frame.
if (!transformer_callback_)
return;
transformer_callback_.Run(std::move(frame));
}
void RTCEncodedAudioStreamTransformer::SendFrameToSink(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (send_frame_to_sink_cb_)
send_frame_to_sink_cb_->OnTransformedFrame(std::move(frame));
}
void RTCEncodedAudioStreamTransformer::SetTransformerCallback(
TransformerCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
transformer_callback_ = std::move(callback);
}
void RTCEncodedAudioStreamTransformer::ResetTransformerCallback() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
transformer_callback_.Reset();
}
bool RTCEncodedAudioStreamTransformer::HasTransformerCallback() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return !transformer_callback_.is_null();
}
bool RTCEncodedAudioStreamTransformer::HasTransformedFrameCallback() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return !!send_frame_to_sink_cb_;
}
rtc::scoped_refptr<webrtc::FrameTransformerInterface>
RTCEncodedAudioStreamTransformer::Delegate() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return delegate_;
}
} // namespace blink