Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(335)

Unified Diff: media/audio/win/waveout_output_win.h

Issue 8591028: Change the way we are sending audio data to driver when using WaveOut API. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | media/audio/win/waveout_output_win.cc » ('j') | media/audio/win/waveout_output_win.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/win/waveout_output_win.h
===================================================================
--- media/audio/win/waveout_output_win.h (revision 110309)
+++ media/audio/win/waveout_output_win.h (working copy)
@@ -6,11 +6,16 @@
#define MEDIA_AUDIO_WIN_WAVEOUT_OUTPUT_WIN_H_
#pragma once
+#include <map>
tommi (sloooow) - chröme 2011/11/18 09:53:21 os includes first
enal1 2011/11/19 00:59:19 Done.
+
#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
#include "base/win/scoped_handle.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_parameters.h"
@@ -29,8 +34,9 @@
class PCMWaveOutAudioOutputStream : public AudioOutputStream {
public:
// The ctor takes all the usual parameters, plus |manager| which is the
- // the audio manager who is creating this object and |device_id| which
- // is provided by the operating system.
+ // the audio manager who is creating this object and on which message loop
+ // "feeder" callbacks are running, and |device_id| which is provided by the
+ // operating system.
PCMWaveOutAudioOutputStream(AudioManagerWin* manager,
const AudioParameters& params,
int num_buffers,
@@ -49,27 +55,73 @@
void QueueNextPacket(WAVEHDR* buffer);
private:
+ // Returns pointer to the n-th buffer.
+ WAVEHDR* GetBuffer(int n) const {
tommi (sloooow) - chröme 2011/11/18 09:53:21 nice. you could move this to the cc file to avoid
enal1 2011/11/19 00:59:19 Done.
+ DCHECK_GE(n, 0);
+ DCHECK_LT(n, num_buffers_);
+ return reinterpret_cast<WAVEHDR*>(buffers_ + n * CbBuffer());
+ }
+
enum State {
PCMA_BRAND_NEW, // Initial state.
PCMA_READY, // Device obtained and ready to play.
PCMA_PLAYING, // Playing audio.
+ PCMA_STOPPING, // Stopping the audio.
PCMA_CLOSED // Device has been released.
};
- // Windows calls us back to feed more data to the device here. See msdn
- // documentation for 'waveOutProc' for details about the parameters.
+ // Size of one buffer in bytes, rounded up to the nearest 16 bytes.
+ DWORD CbBuffer() const {
tommi (sloooow) - chröme 2011/11/18 09:53:21 CbBuffer -> BufferSize Also, return size_t?
enal1 2011/11/19 00:59:19 Done.
+ return (sizeof(WAVEHDR) + buffer_size_ + 15u) & static_cast<DWORD>(-16);
tommi (sloooow) - chröme 2011/11/18 09:53:21 instead of static_cast<DWORD>(-16), can you just u
enal1 2011/11/19 00:59:19 In general, 0xFFFFFFF0 is bad -- it can become a p
+ }
+
+ // Windows calls us back to free the buffer. See msdn documentation for
+ // 'waveOutProc' for details about the parameters.
static void CALLBACK WaveCallback(HWAVEOUT hwo, UINT msg, DWORD_PTR instance,
DWORD_PTR param1, DWORD_PTR param2);
+ // Feed the buffer to waveOut.
+ // Called on the audio manager thread.
+ static void FeedBuffer(PCMWaveOutAudioOutputStream* stream,
+ WAVEHDR* buffer,
+ HWAVEOUT hwo,
+ DWORD ordinal);
+
// If windows reports an error this function handles it and passes it to
// the attached AudioSourceCallback::OnError().
void HandleError(MMRESULT error);
- // Allocates and prepares the memory that will be used for playback. Only
- // two buffers are created.
+ // Allocates and prepares the memory that will be used for playback.
tommi (sloooow) - chröme 2011/11/18 09:53:21 add an empty line above this one. same throughout
enal1 2011/11/19 00:59:19 Done.
void SetupBuffers();
// Deallocates the memory allocated in SetupBuffers.
void FreeBuffers();
+ // Globals-related functions.
tommi (sloooow) - chröme 2011/11/18 09:53:21 This comment isn't very useful. Can you document
enal1 2011/11/19 00:59:19 Done.
+ static void InitializeGlobalsIfNecessary();
+ static void CleanupGlobals(void* not_used);
+ // Static lock guarding access to globals.
+ // We are not doing any expensive operations under this lock --
+ // adding/searching/removing object to/in/from map of all live objects, and
+ // trying to acquire object lock, so hopefully we can live with one global
+ // lock for all audio streams. If contention ever becomes the problem we
+ // can use hash of stream address to use one of several global locks.
+ static base::Lock g_lock_;
tommi (sloooow) - chröme 2011/11/18 09:53:21 We should avoid global objects that require constr
enal1 2011/11/19 00:59:19 Done.
+
+ // When playing, every instance of our audio stream has associated ordinal.
+ // Callback that feeds the audio thread verifies that stream is still alive
+ // by looking stream address and its ordinal in the map of all streams.
tommi (sloooow) - chröme 2011/11/18 09:53:21 by looking stream address -> by looking at the str
enal1 2011/11/19 00:59:19 Done.
+ // Stream is not touched before check is complete. This way we don't
tommi (sloooow) - chröme 2011/11/18 09:53:21 "Stream is not touched before check is complete"
enal1 2011/11/19 00:59:19 Done.
+ // have to wait for all scheduled callbacks to finish when stopping audio
+ // stream. Ordinal is needed because audio stream can be deleted and new one
+ // with same address created.
+ // Ordinal overflow would be a problem only if some scheduled feeder callback
+ // would not run before 4.2*10**9 play() calls are executed, impossible for
+ // now...
+ static volatile DWORD g_ordinal_;
+
+ // Map of all live streams with their ordinals.
+ static scoped_ptr<std::map<PCMWaveOutAudioOutputStream*, DWORD> >
+ g_streams_map_;
+
// Reader beware. Visual C has stronger guarantees on volatile vars than
// most people expect. In fact, it has release semantics on write and
// acquire semantics on reads. See the msdn documentation.
@@ -107,19 +159,17 @@
// Handle to the instance of the wave device.
HWAVEOUT waveout_;
- // Pointer to the first allocated audio buffer. This object owns it.
- WAVEHDR* buffer_;
+ // Pointer to the allocated audio buffers, we allocate all buffers in one big
+ // chunk. Stream owns them.
tommi (sloooow) - chröme 2011/11/18 09:53:21 I prefer "This object owns it" to "Stream owns the
+ char* buffers_;
- // Lock used to prevent stopping the hardware callback thread while it is
- // pending for data or feeding it to audio driver, because doing that causes
- // the deadlock. Main thread gets that lock before stopping the playback.
- // Callback tries to acquire that lock before entering critical code. If
- // acquire fails then main thread is stopping the playback, callback should
- // immediately return.
- // Use Windows-specific lock, not Chrome one, because there is limited set of
- // functions callback can use.
- CRITICAL_SECTION lock_;
+ // Lock used to avoid the conflict between filling audio buffers and
+ // stopping the stream.
+ base::Lock lock_;
+ // Ordinal of current stream when playing.
+ DWORD ordinal_;
+
DISALLOW_COPY_AND_ASSIGN(PCMWaveOutAudioOutputStream);
};
« no previous file with comments | « no previous file | media/audio/win/waveout_output_win.cc » ('j') | media/audio/win/waveout_output_win.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698