#include "media/audio/audio_device_thread.h"
#include <limits>
#include <ostream>
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "media/base/media_switches.h"
namespace media {
AudioDeviceThread::Callback::Callback(const AudioParameters& audio_parameters,
uint32_t segment_length,
uint32_t total_segments)
: audio_parameters_(audio_parameters),
memory_length_(
base::CheckMul(segment_length, total_segments).ValueOrDie()),
total_segments_(total_segments),
segment_length_(segment_length) {
CHECK_GT(total_segments_, 0u);
thread_checker_.DetachFromThread();
}
AudioDeviceThread::Callback::~Callback() = default;
void AudioDeviceThread::Callback::InitializeOnAudioThread() {
DCHECK(thread_checker_.CalledOnValidThread())
<< "Thread checker was attached on the wrong thread";
MapSharedMemory();
}
bool AudioDeviceThread::Callback::WillConfirmReadsViaShmem() const {
return false;
}
AudioDeviceThread::AudioDeviceThread(Callback* callback,
base::SyncSocket::ScopedHandle socket,
const char* thread_name,
base::ThreadType thread_type)
: callback_(callback),
thread_name_(thread_name),
socket_(std::move(socket)),
send_socket_messages_(!callback_->WillConfirmReadsViaShmem()) {
#if defined(ARCH_CPU_X86)
constexpr size_t kStackSize = 256 * 1024;
#else
constexpr size_t kStackSize = 0;
#endif
CHECK(base::PlatformThread::CreateWithType(kStackSize, this, &thread_handle_,
thread_type));
DCHECK(!thread_handle_.is_null());
}
AudioDeviceThread::~AudioDeviceThread() {
in_shutdown_ = true;
socket_.Shutdown();
if (thread_handle_.is_null())
return;
base::PlatformThread::Join(thread_handle_);
}
#if BUILDFLAG(IS_APPLE)
base::TimeDelta AudioDeviceThread::GetRealtimePeriod() {
return callback_->buffer_duration();
}
#endif
void AudioDeviceThread::ThreadMain() {
base::PlatformThread::SetName(thread_name_);
callback_->InitializeOnAudioThread();
uint32_t buffer_index = 0;
while (true) {
uint32_t pending_data = 0;
size_t bytes_read = socket_.Receive(base::byte_span_from_ref(pending_data));
if (bytes_read != sizeof(pending_data))
break;
if (pending_data == std::numeric_limits<uint32_t>::max() - 1) {
in_shutdown_ = true;
break;
}
if (pending_data != std::numeric_limits<uint32_t>::max())
callback_->Process(pending_data);
if (send_socket_messages_) {
++buffer_index;
size_t bytes_sent = socket_.Send(base::byte_span_from_ref(buffer_index));
if (bytes_sent != sizeof(buffer_index)) {
break;
}
}
}
if (!in_shutdown_.load()) {
callback_->OnSocketError();
}
}
}