summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/media/audio_renderer_impl.h
blob: 5c34a7dd8e30a27ca6473ef4fb7164c7dc2d0b91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Audio rendering unit utilizing audio output stream provided by browser
// process through IPC.
//
// Relationship of classes.
//
//    AudioRendererHost                AudioRendererImpl
//           ^                                ^
//           |                                |
//           v                 IPC            v
//   ResourceMessageFilter <---------> AudioMessageFilter
//
// Implementation of interface with audio device is in AudioRendererHost and
// it provides services and entry points in ResourceMessageFilter, allowing
// usage of IPC calls to interact with audio device. AudioMessageFilter acts
// as a portal for IPC calls and does no more than delegation.
//
// Transportation of audio buffer is done by using shared memory, after
// OnCreateStream is executed, OnCreated would be called along with a
// SharedMemoryHandle upon successful creation of audio output stream in the
// browser process. The same piece of shared memory would be used during the
// lifetime of this unit.
//
// This class lives inside three threads during it's lifetime, namely:
// 1. IO thread.
//    The thread within which this class receives all the IPC messages and
//    IPC communications can only happen in this thread.
// 2. Pipeline thread
//    Initialization of filter and proper stopping of filters happens here.
//    Properties of this filter is also set in this thread.
// 3. Audio decoder thread (If there's one.)
//    Responsible for decoding audio data and gives raw PCM data to this object.

#ifndef CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
#define CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
#pragma once

#include "base/gtest_prod_util.h"
#include "base/scoped_ptr.h"
#include "base/lock.h"
#include "base/shared_memory.h"
#include "chrome/renderer/audio_message_filter.h"
#include "media/audio/audio_io.h"
#include "media/base/factory.h"
#include "media/base/filters.h"
#include "media/filters/audio_renderer_base.h"

class AudioMessageFilter;

class AudioRendererImpl : public media::AudioRendererBase,
                          public AudioMessageFilter::Delegate,
                          public MessageLoop::DestructionObserver {
 public:
  // Methods called on render thread ------------------------------------------
  // Methods called during construction.
  static media::FilterFactory* CreateFactory(AudioMessageFilter* filter) {
    return new media::FilterFactoryImpl1<AudioRendererImpl,
                                         AudioMessageFilter*>(filter);
  }
  static bool IsMediaFormatSupported(const media::MediaFormat& format);

  // Methods called on IO thread ----------------------------------------------
  // AudioMessageFilter::Delegate methods, called by AudioMessageFilter.
  void OnRequestPacket(uint32 bytes_in_buffer,
                       const base::Time& message_timestamp);
  void OnStateChanged(const ViewMsg_AudioStreamState_Params& state);
  void OnCreated(base::SharedMemoryHandle handle, uint32 length);
  void OnLowLatencyCreated(base::SharedMemoryHandle handle,
                           base::SyncSocket::Handle socket_handle,
                           uint32 length);
  void OnVolume(double volume);

  // Methods called on pipeline thread ----------------------------------------
  // media::MediaFilter implementation.
  virtual void SetPlaybackRate(float rate);
  virtual void Pause(media::FilterCallback* callback);
  virtual void Seek(base::TimeDelta time, media::FilterCallback* callback);
  virtual void Play(media::FilterCallback* callback);

  // media::AudioRenderer implementation.
  virtual void SetVolume(float volume);

 protected:
  // Methods called on audio renderer thread ----------------------------------
  // These methods are called from AudioRendererBase.
  virtual bool OnInitialize(const media::MediaFormat& media_format);
  virtual void OnStop();

  // Called when the decoder completes a Read().
  virtual void OnReadComplete(media::Buffer* buffer_in);

 private:
  friend class media::FilterFactoryImpl1<AudioRendererImpl,
                                         AudioMessageFilter*>;

  // For access to constructor and IO thread methods.
  friend class AudioRendererImplTest;
  FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, Stop);
  FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest,
                           DestroyedMessageLoop_OnReadComplete);

  explicit AudioRendererImpl(AudioMessageFilter* filter);
  virtual ~AudioRendererImpl();

  // Helper methods.
  // Convert number of bytes to duration of time using information about the
  // number of channels, sample rate and sample bits.
  base::TimeDelta ConvertToDuration(int bytes);

  // Methods call on IO thread ------------------------------------------------
  // The following methods are tasks posted on the IO thread that needs to
  // be executed on that thread. They interact with AudioMessageFilter and
  // sends IPC messages on that thread.
  void CreateStreamTask(AudioManager::Format format, int channels,
                        int sample_rate, int bits_per_sample);
  void PlayTask();
  void PauseTask();
  void SeekTask();
  void SetVolumeTask(double volume);
  void NotifyPacketReadyTask();
  void DestroyTask();

  // Called on IO thread when message loop is dying.
  virtual void WillDestroyCurrentMessageLoop();

  // Information about the audio stream.
  int channels_;
  int sample_rate_;
  int sample_bits_;
  uint32 bytes_per_second_;

  scoped_refptr<AudioMessageFilter> filter_;

  // ID of the stream created in the browser process.
  int32 stream_id_;

  // Memory shared by the browser process for audio buffer.
  scoped_ptr<base::SharedMemory> shared_memory_;
  uint32 shared_memory_size_;

  // Message loop for the IO thread.
  MessageLoop* io_loop_;

  // Protects:
  // - |stopped_|
  // - |pending_request_|
  // - |request_timestamp_|
  // - |request_delay_|
  Lock lock_;

  // A flag that indicates this filter is called to stop.
  bool stopped_;

  // A flag that indicates an outstanding packet request.
  bool pending_request_;

  // The time when a request is made.
  base::Time request_timestamp_;

  // The delay for the requested packet to be played.
  base::TimeDelta request_delay_;

  // State variables for prerolling.
  bool prerolling_;

  // Remaining bytes for prerolling to complete.
  uint32 preroll_bytes_;

  DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl);
};

#endif  // CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_