Home | History | Annotate | Download | only in media
      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