summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorenal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 20:24:52 +0000
committerenal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 20:24:52 +0000
commit474c37af2d3afbc3d4bb78a0aac813f338fa7e5c (patch)
tree33d12ccbc7f679e98bba9bebe7b5e4b4603a353e /media
parentec865268f9c9c9ef34f211a1257851b0482d1870 (diff)
downloadchromium_src-474c37af2d3afbc3d4bb78a0aac813f338fa7e5c.zip
chromium_src-474c37af2d3afbc3d4bb78a0aac813f338fa7e5c.tar.gz
chromium_src-474c37af2d3afbc3d4bb78a0aac813f338fa7e5c.tar.bz2
Fix problem when 'ended' event was fired before stream really ended.
That caused impression that rewind does not work. With that change small JS program var a = new Audio("file:///home/enal/temp/click2/click2.wav"); var num_played = 0; a.addEventListener('canplaythrough', function() { a.play(); }); a.addEventListener('ended', function() { num_played ++; if (num_played < 10) { a.currentTime = 0; a.play(); } }); works correctly, you hear 10 clicks one after another, and it takes ~1.5 seconds to play all 10 sounds (one click is 146ms). Current Chrome plays only beginnings of the first 9 clicks and then entire 10th click -- 'ended' event fires too early, so rewind stops audio playback for all clicks but last one. With that fix you can easily create pool of audio objects -- on 'ended' event just add audio object to the pool. Fix consists of 2 parts: 1) When using low-latency code path renderer not only fills the buffer with data, but also writes length of data at the end of buffer. That allows host process to pass correct byte counts to renderer. Counter is written at the endo of buffer, and by default it is set to buffer length, so no changes to existing clients are necessary. 3) Renderer now keeps track of the earliest time playback can end based on the number of rendered bytes, and will not call 'ended' callback till that time. PS. After several comments I changed chrome code to make it much harder for code to get buffer overrun. I was pointed that native client can write bogus size of data into buffer, so function in chrome that reads size of data now has extra argument -- max size of buffer, and returns min(max size of buffer, size of data reported by client). This way min() is always called. PPS. That is much scaled down version of the CL, it does not affect lot of audio code paths... BUG=http://code.google.com/p/chromium/issues/detail?id=78992 http://codereview.chromium.org/7328030 Review URL: http://codereview.chromium.org/7328030 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97905 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/audio_util.cc40
-rw-r--r--media/audio/audio_util.h15
2 files changed, 55 insertions, 0 deletions
diff --git a/media/audio/audio_util.cc b/media/audio/audio_util.cc
index 18e2abb..fe5fb10 100644
--- a/media/audio/audio_util.cc
+++ b/media/audio/audio_util.cc
@@ -8,13 +8,19 @@
// Implemented as templates to allow 8, 16 and 32 bit implementations.
// 8 bit is unsigned and biased by 128.
+#include <algorithm>
+
+#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/logging.h"
+#include "base/shared_memory.h"
#include "media/audio/audio_util.h"
#if defined(OS_MACOSX)
#include "media/audio/mac/audio_low_latency_output_mac.h"
#endif
+using base::subtle::Atomic32;
+
namespace media {
// TODO(fbarchard): Convert to intrinsics for better efficiency.
@@ -234,4 +240,38 @@ double GetAudioHardwareSampleRate()
#endif
}
+// When transferring data in the shared memory, first word is size of data
+// in bytes. Actual data starts immediately after it.
+
+uint32 TotalSharedMemorySizeInBytes(uint32 packet_size) {
+ // Need to reserve extra 4 bytes for size of data.
+ return packet_size + sizeof(Atomic32);
+}
+
+uint32 PacketSizeSizeInBytes(uint32 shared_memory_created_size) {
+ return shared_memory_created_size - sizeof(Atomic32);
+}
+
+uint32 GetActualDataSizeInBytes(base::SharedMemory* shared_memory,
+ uint32 shared_memory_size) {
+ char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size;
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3);
+
+ // Actual data size stored in the beginning of the buffer.
+ uint32 actual_data_size =
+ base::subtle::Acquire_Load(reinterpret_cast<volatile Atomic32*>(ptr));
+ return std::min(actual_data_size, shared_memory_size);
+}
+
+void SetActualDataSizeInBytes(base::SharedMemory* shared_memory,
+ uint32 shared_memory_size,
+ uint32 actual_data_size) {
+ char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size;
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3);
+
+ // Set actual data size in the beginning of the buffer.
+ base::subtle::Release_Store(reinterpret_cast<volatile Atomic32*>(ptr),
+ actual_data_size);
+}
+
} // namespace media
diff --git a/media/audio/audio_util.h b/media/audio/audio_util.h
index 0d65e19..a2fa15e 100644
--- a/media/audio/audio_util.h
+++ b/media/audio/audio_util.h
@@ -9,6 +9,10 @@
#include "base/basictypes.h"
+namespace base {
+class SharedMemory;
+}
+
namespace media {
// For all audio functions 3 audio formats are supported:
@@ -77,6 +81,17 @@ void InterleaveFloatToInt16(const std::vector<float*>& source,
// Returns the default audio hardware sample-rate.
double GetAudioHardwareSampleRate();
+// Functions that handle data buffer passed between processes in the shared
+// memory. Called on both IPC sides.
+
+uint32 TotalSharedMemorySizeInBytes(uint32 packet_size);
+uint32 PacketSizeSizeInBytes(uint32 shared_memory_created_size);
+uint32 GetActualDataSizeInBytes(base::SharedMemory* shared_memory,
+ uint32 shared_memory_size);
+void SetActualDataSizeInBytes(base::SharedMemory* shared_memory,
+ uint32 shared_memory_size,
+ uint32 actual_data_size);
+
} // namespace media
#endif // MEDIA_AUDIO_AUDIO_UTIL_H_