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 12 using media::AudioBus; 13 14 namespace content { 15 16 AudioInputSyncWriter::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 45 AudioInputSyncWriter::~AudioInputSyncWriter() {} 46 47 // TODO(henrika): Combine into one method (including Write). 48 void AudioInputSyncWriter::UpdateRecordedBytes(uint32 bytes) { 49 socket_->Send(&bytes, sizeof(bytes)); 50 } 51 52 void 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 << "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 << "Audio input data delay unexpectedly long: delay = " 70 << interval.InMilliseconds() << "ms."; 71 } 72 } 73 if (!oss.str().empty()) 74 MediaStreamManager::SendMessageToNativeLog(oss.str()); 75 76 last_write_time_ = base::Time::Now(); 77 #endif 78 79 // Write audio parameters to shared memory. 80 uint8* ptr = static_cast<uint8*>(shared_memory_->memory()); 81 ptr += current_segment_id_ * shared_memory_segment_size_; 82 media::AudioInputBuffer* buffer = 83 reinterpret_cast<media::AudioInputBuffer*>(ptr); 84 buffer->params.volume = volume; 85 buffer->params.size = audio_bus_memory_size_; 86 buffer->params.key_pressed = key_pressed; 87 88 // Copy data from the native audio layer into shared memory using pre- 89 // allocated audio buses. 90 media::AudioBus* audio_bus = audio_buses_[current_segment_id_]; 91 data->CopyTo(audio_bus); 92 93 if (++current_segment_id_ >= shared_memory_segment_count_) 94 current_segment_id_ = 0; 95 } 96 97 void AudioInputSyncWriter::Close() { 98 socket_->Close(); 99 } 100 101 bool AudioInputSyncWriter::Init() { 102 socket_.reset(new base::CancelableSyncSocket()); 103 foreign_socket_.reset(new base::CancelableSyncSocket()); 104 return base::CancelableSyncSocket::CreatePair(socket_.get(), 105 foreign_socket_.get()); 106 } 107 108 #if defined(OS_WIN) 109 110 bool AudioInputSyncWriter::PrepareForeignSocketHandle( 111 base::ProcessHandle process_handle, 112 base::SyncSocket::Handle* foreign_handle) { 113 ::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(), 114 process_handle, foreign_handle, 115 0, FALSE, DUPLICATE_SAME_ACCESS); 116 return (*foreign_handle != 0); 117 } 118 119 #else 120 121 bool AudioInputSyncWriter::PrepareForeignSocketHandle( 122 base::ProcessHandle process_handle, 123 base::FileDescriptor* foreign_handle) { 124 foreign_handle->fd = foreign_socket_->handle(); 125 foreign_handle->auto_close = false; 126 return (foreign_handle->fd != -1); 127 } 128 129 #endif 130 131 } // namespace content 132