1 // Copyright 2018 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 "media/audio/audio_output_device_thread_callback.h"
6 
7 #include <utility>
8 
9 #include "base/logging.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/trace_event/trace_event.h"
12 
13 namespace media {
14 
AudioOutputDeviceThreadCallback(const media::AudioParameters & audio_parameters,base::UnsafeSharedMemoryRegion shared_memory_region,media::AudioRendererSink::RenderCallback * render_callback)15 AudioOutputDeviceThreadCallback::AudioOutputDeviceThreadCallback(
16     const media::AudioParameters& audio_parameters,
17     base::UnsafeSharedMemoryRegion shared_memory_region,
18     media::AudioRendererSink::RenderCallback* render_callback)
19     : media::AudioDeviceThread::Callback(
20           audio_parameters,
21           ComputeAudioOutputBufferSize(audio_parameters),
22           /*segment count*/ 1),
23       shared_memory_region_(std::move(shared_memory_region)),
24       render_callback_(render_callback),
25       callback_num_(0) {
26   // CHECK that the shared memory is large enough. The memory allocated must be
27   // at least as large as expected.
28   CHECK(memory_length_ <= shared_memory_region_.GetSize());
29 }
30 
31 AudioOutputDeviceThreadCallback::~AudioOutputDeviceThreadCallback() = default;
32 
MapSharedMemory()33 void AudioOutputDeviceThreadCallback::MapSharedMemory() {
34   CHECK_EQ(total_segments_, 1u);
35   shared_memory_mapping_ = shared_memory_region_.MapAt(0, memory_length_);
36   CHECK(shared_memory_mapping_.IsValid());
37 
38   media::AudioOutputBuffer* buffer =
39       reinterpret_cast<media::AudioOutputBuffer*>(
40           shared_memory_mapping_.memory());
41   output_bus_ = media::AudioBus::WrapMemory(audio_parameters_, buffer->audio);
42   output_bus_->set_is_bitstream_format(audio_parameters_.IsBitstreamFormat());
43 }
44 
45 // Called whenever we receive notifications about pending data.
Process(uint32_t control_signal)46 void AudioOutputDeviceThreadCallback::Process(uint32_t control_signal) {
47   callback_num_++;
48 
49   // Read and reset the number of frames skipped.
50   media::AudioOutputBuffer* buffer =
51       reinterpret_cast<media::AudioOutputBuffer*>(
52           shared_memory_mapping_.memory());
53   uint32_t frames_skipped = buffer->params.frames_skipped;
54   buffer->params.frames_skipped = 0;
55 
56   TRACE_EVENT_BEGIN2("audio", "AudioOutputDevice::FireRenderCallback",
57                      "callback_num", callback_num_, "frames skipped",
58                      frames_skipped);
59 
60   base::TimeDelta delay =
61       base::TimeDelta::FromMicroseconds(buffer->params.delay_us);
62 
63   base::TimeTicks delay_timestamp =
64       base::TimeTicks() +
65       base::TimeDelta::FromMicroseconds(buffer->params.delay_timestamp_us);
66 
67   DVLOG(4) << __func__ << " delay:" << delay << " delay_timestamp:" << delay
68            << " frames_skipped:" << frames_skipped;
69 
70   // When playback starts, we get an immediate callback to Process to make sure
71   // that we have some data, we'll get another one after the device is awake and
72   // ingesting data, which is what we want to track with this trace.
73   if (callback_num_ == 2)
74     TRACE_EVENT_ASYNC_END0("audio", "StartingPlayback", this);
75 
76   // Update the audio-delay measurement, inform about the number of skipped
77   // frames, and ask client to render audio.  Since |output_bus_| is wrapping
78   // the shared memory the Render() call is writing directly into the shared
79   // memory.
80   render_callback_->Render(delay, delay_timestamp, frames_skipped,
81                            output_bus_.get());
82 
83   if (audio_parameters_.IsBitstreamFormat()) {
84     buffer->params.bitstream_data_size = output_bus_->GetBitstreamDataSize();
85     buffer->params.bitstream_frames = output_bus_->GetBitstreamFrames();
86   }
87 
88   TRACE_EVENT_END2("audio", "AudioOutputDevice::FireRenderCallback",
89                    "timestamp (ms)",
90                    (delay_timestamp - base::TimeTicks()).InMillisecondsF(),
91                    "delay (ms)", delay.InMillisecondsF());
92 }
93 
CurrentThreadIsAudioDeviceThread()94 bool AudioOutputDeviceThreadCallback::CurrentThreadIsAudioDeviceThread() {
95   return thread_checker_.CalledOnValidThread();
96 }
97 
InitializePlayStartTime()98 void AudioOutputDeviceThreadCallback::InitializePlayStartTime() {}
99 
100 }  // namespace media
101