summaryrefslogtreecommitdiffstats
path: root/content/browser/renderer_host/media/audio_renderer_host.h
diff options
context:
space:
mode:
Diffstat (limited to 'content/browser/renderer_host/media/audio_renderer_host.h')
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.h222
1 files changed, 222 insertions, 0 deletions
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
new file mode 100644
index 0000000..944857f
--- /dev/null
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -0,0 +1,222 @@
+// Copyright (c) 2011 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.
+//
+// AudioRendererHost serves audio related requests from AudioRenderer which
+// lives inside the render process and provide access to audio hardware.
+//
+// This class is owned by BrowserRenderProcessHost, and instantiated on UI
+// thread, but all other operations and method calls happen on IO thread, so we
+// need to be extra careful about the lifetime of this object. AudioManager is a
+// singleton and created in IO thread, audio output streams are also created in
+// the IO thread, so we need to destroy them also in IO thread. After this class
+// is created, a task of OnInitialized() is posted on IO thread in which
+// singleton of AudioManager is created and.
+//
+// Here's an example of a typical IPC dialog for audio:
+//
+// Renderer AudioRendererHost
+// | |
+// | CreateStream > |
+// | < Created |
+// | |
+// | Play > |
+// | < Playing | time
+// | |
+// | < RequestAudioPacket |
+// | AudioPacketReady > |
+// | ... |
+// | < RequestAudioPacket |
+// | AudioPacketReady > |
+// | |
+// | ... |
+// | < RequestAudioPacket |
+// | AudioPacketReady > |
+// | ... |
+// | Pause > |
+// | < Paused |
+// | ... |
+// | Start > |
+// | < Started |
+// | ... |
+// | Close > |
+// v v
+
+// The above mode of operation uses relatively big buffers and has latencies
+// of 50 ms or more. There is a second mode of operation which is low latency.
+// For low latency audio, the picture above is modified by not having the
+// RequestAudioPacket and the AudioPacketReady messages, instead a SyncSocket
+// pair is used to signal buffer readiness without having to route messages
+// using the IO thread.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
+#pragma once
+
+#include <map>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process.h"
+#include "base/shared_memory.h"
+#include "content/browser/browser_message_filter.h"
+#include "content/browser/browser_thread.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_output_controller.h"
+#include "media/audio/simple_sources.h"
+
+class AudioManager;
+struct AudioParameters;
+
+class AudioRendererHost : public BrowserMessageFilter,
+ public media::AudioOutputController::EventHandler {
+ public:
+ typedef std::pair<int32, int> AudioEntryId;
+
+ struct AudioEntry {
+ AudioEntry();
+ ~AudioEntry();
+
+ // The AudioOutputController that manages the audio stream.
+ scoped_refptr<media::AudioOutputController> controller;
+
+ // Render view ID that requested the audio stream.
+ int32 render_view_id;
+
+ // The audio stream ID in the render view.
+ int stream_id;
+
+ // Shared memory for transmission of the audio data.
+ base::SharedMemory shared_memory;
+
+ // The synchronous reader to be used by the controller. We have the
+ // ownership of the reader.
+ scoped_ptr<media::AudioOutputController::SyncReader> reader;
+
+ bool pending_buffer_request;
+
+ // Set to true after we called Close() for the controller.
+ bool pending_close;
+ };
+
+ typedef std::map<AudioEntryId, AudioEntry*> AudioEntryMap;
+
+ // Called from UI thread from the owner of this object.
+ AudioRendererHost();
+
+
+ // BrowserMessageFilter implementation.
+ virtual void OnChannelClosing();
+ virtual void OnDestruct() const;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // AudioOutputController::EventHandler implementations.
+ virtual void OnCreated(media::AudioOutputController* controller);
+ virtual void OnPlaying(media::AudioOutputController* controller);
+ virtual void OnPaused(media::AudioOutputController* controller);
+ virtual void OnError(media::AudioOutputController* controller,
+ int error_code);
+ virtual void OnMoreData(media::AudioOutputController* controller,
+ AudioBuffersState buffers_state);
+
+ private:
+ friend class AudioRendererHostTest;
+ friend class BrowserThread;
+ friend class DeleteTask<AudioRendererHost>;
+ friend class MockAudioRendererHost;
+ FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, CreateMockStream);
+ FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, MockStreamDataConversation);
+
+ virtual ~AudioRendererHost();
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Methods called on IO thread.
+ // Returns true if the message is an audio related message and should be
+ // handled by this class.
+ bool IsAudioRendererHostMessage(const IPC::Message& message);
+
+ // Audio related IPC message handlers.
+ // Creates an audio output stream with the specified format. If this call is
+ // successful this object would keep an internal entry of the stream for the
+ // required properties.
+ void OnCreateStream(const IPC::Message& msg, int stream_id,
+ const AudioParameters& params,
+ bool low_latency);
+
+ // Play the audio stream referenced by |stream_id|.
+ void OnPlayStream(const IPC::Message& msg, int stream_id);
+
+ // Pause the audio stream referenced by |stream_id|.
+ void OnPauseStream(const IPC::Message& msg, int stream_id);
+
+ // Discard all audio data in stream referenced by |stream_id|.
+ void OnFlushStream(const IPC::Message& msg, int stream_id);
+
+ // Close the audio stream referenced by |stream_id|.
+ void OnCloseStream(const IPC::Message& msg, int stream_id);
+
+ // Set the volume of the audio stream referenced by |stream_id|.
+ void OnSetVolume(const IPC::Message& msg, int stream_id, double volume);
+
+ // Get the volume of the audio stream referenced by |stream_id|.
+ void OnGetVolume(const IPC::Message& msg, int stream_id);
+
+ // Notify packet has been prepared for the audio stream.
+ void OnNotifyPacketReady(const IPC::Message& msg, int stream_id,
+ uint32 packet_size);
+
+ // Complete the process of creating an audio stream. This will set up the
+ // shared memory or shared socket in low latency mode.
+ void DoCompleteCreation(media::AudioOutputController* controller);
+
+ // Send a state change message to the renderer.
+ void DoSendPlayingMessage(media::AudioOutputController* controller);
+ void DoSendPausedMessage(media::AudioOutputController* controller);
+
+ // Request more data from the renderer. This method is used only in normal
+ // latency mode.
+ void DoRequestMoreData(media::AudioOutputController* controller,
+ AudioBuffersState buffers_state);
+
+ // Handle error coming from audio stream.
+ void DoHandleError(media::AudioOutputController* controller, int error_code);
+
+ // Send an error message to the renderer.
+ void SendErrorMessage(int32 render_view_id, int32 stream_id);
+
+ // Delete all audio entry and all audio streams
+ void DeleteEntries();
+
+ // Closes the stream. The stream is then deleted in DeleteEntry() after it
+ // is closed.
+ void CloseAndDeleteStream(AudioEntry* entry);
+
+ // Called on the audio thread after the audio stream is closed.
+ void OnStreamClosed(AudioEntry* entry);
+
+ // Delete an audio entry and close the related audio stream.
+ void DeleteEntry(AudioEntry* entry);
+
+ // Delete audio entry and close the related audio stream due to an error,
+ // and error message is send to the renderer.
+ void DeleteEntryOnError(AudioEntry* entry);
+
+ // A helper method to look up a AudioEntry with a tuple of render view
+ // id and stream id. Returns NULL if not found.
+ AudioEntry* LookupById(int render_view_id, int stream_id);
+
+ // Search for a AudioEntry having the reference to |controller|.
+ // This method is used to look up an AudioEntry after a controller
+ // event is received.
+ AudioEntry* LookupByController(media::AudioOutputController* controller);
+
+ // A map of id to audio sources.
+ AudioEntryMap audio_entries_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererHost);
+};
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_