1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/renderer_host/media/audio_input_sync_writer.h" 6 7#include <algorithm> 8 9#include "base/memory/shared_memory.h" 10#include "content/browser/renderer_host/media/media_stream_manager.h" 11 12using media::AudioBus; 13 14namespace content { 15 16AudioInputSyncWriter::AudioInputSyncWriter(base::SharedMemory* shared_memory, 17 int shared_memory_segment_count, 18 const media::AudioParameters& params) 19 : shared_memory_(shared_memory), 20 shared_memory_segment_count_(shared_memory_segment_count), 21 current_segment_id_(0), 22 creation_time_(base::Time::Now()), 23 audio_bus_memory_size_(AudioBus::CalculateMemorySize(params)) { 24 DCHECK_GT(shared_memory_segment_count, 0); 25 DCHECK_EQ(shared_memory->requested_size() % shared_memory_segment_count, 0u); 26 shared_memory_segment_size_ = 27 shared_memory->requested_size() / shared_memory_segment_count; 28 DVLOG(1) << "SharedMemory::requested_size: " 29 << shared_memory->requested_size(); 30 DVLOG(1) << "shared_memory_segment_count: " << shared_memory_segment_count; 31 DVLOG(1) << "audio_bus_memory_size: " << audio_bus_memory_size_; 32 33 // Create vector of audio buses by wrapping existing blocks of memory. 34 uint8* ptr = static_cast<uint8*>(shared_memory_->memory()); 35 for (int i = 0; i < shared_memory_segment_count; ++i) { 36 media::AudioInputBuffer* buffer = 37 reinterpret_cast<media::AudioInputBuffer*>(ptr); 38 scoped_ptr<media::AudioBus> audio_bus = 39 media::AudioBus::WrapMemory(params, buffer->audio); 40 audio_buses_.push_back(audio_bus.release()); 41 ptr += shared_memory_segment_size_; 42 } 43} 44 45AudioInputSyncWriter::~AudioInputSyncWriter() {} 46 47// TODO(henrika): Combine into one method (including Write). 48void AudioInputSyncWriter::UpdateRecordedBytes(uint32 bytes) { 49 socket_->Send(&bytes, sizeof(bytes)); 50} 51 52void AudioInputSyncWriter::Write(const media::AudioBus* data, 53 double volume, 54 bool key_pressed) { 55#if !defined(OS_ANDROID) 56 static const base::TimeDelta kLogDelayThreadhold = 57 base::TimeDelta::FromMilliseconds(500); 58 59 std::ostringstream oss; 60 if (last_write_time_.is_null()) { 61 // This is the first time Write is called. 62 base::TimeDelta interval = base::Time::Now() - creation_time_; 63 oss << "AISW::Write: audio input data received for the first time: delay " 64 "= " << interval.InMilliseconds() << "ms"; 65 66 } else { 67 base::TimeDelta interval = base::Time::Now() - last_write_time_; 68 if (interval > kLogDelayThreadhold) { 69 oss << "AISW::Write: audio input data delay unexpectedly long: delay = " 70 << interval.InMilliseconds() << "ms"; 71 } 72 } 73 if (!oss.str().empty()) { 74 MediaStreamManager::SendMessageToNativeLog(oss.str()); 75 DVLOG(1) << oss.str(); 76 } 77 78 last_write_time_ = base::Time::Now(); 79#endif 80 81 // Write audio parameters to shared memory. 82 uint8* ptr = static_cast<uint8*>(shared_memory_->memory()); 83 ptr += current_segment_id_ * shared_memory_segment_size_; 84 media::AudioInputBuffer* buffer = 85 reinterpret_cast<media::AudioInputBuffer*>(ptr); 86 buffer->params.volume = volume; 87 buffer->params.size = audio_bus_memory_size_; 88 buffer->params.key_pressed = key_pressed; 89 90 // Copy data from the native audio layer into shared memory using pre- 91 // allocated audio buses. 92 media::AudioBus* audio_bus = audio_buses_[current_segment_id_]; 93 data->CopyTo(audio_bus); 94 95 if (++current_segment_id_ >= shared_memory_segment_count_) 96 current_segment_id_ = 0; 97} 98 99void AudioInputSyncWriter::Close() { 100 socket_->Close(); 101} 102 103bool AudioInputSyncWriter::Init() { 104 socket_.reset(new base::CancelableSyncSocket()); 105 foreign_socket_.reset(new base::CancelableSyncSocket()); 106 return base::CancelableSyncSocket::CreatePair(socket_.get(), 107 foreign_socket_.get()); 108} 109 110bool AudioInputSyncWriter::PrepareForeignSocket( 111 base::ProcessHandle process_handle, 112 base::SyncSocket::TransitDescriptor* descriptor) { 113 return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor); 114} 115 116 117} // namespace content 118