Index: media/audio/audio_output_mixer.cc |
=================================================================== |
--- media/audio/audio_output_mixer.cc (revision 133745) |
+++ media/audio/audio_output_mixer.cc (working copy) |
@@ -5,6 +5,7 @@ |
#include "media/audio/audio_output_mixer.h" |
#include <algorithm> |
+#include <utility> |
#include "base/bind.h" |
#include "base/compiler_specific.h" |
@@ -44,6 +45,7 @@ |
stream->Close(); |
return false; |
} |
+ buffer_data_.clear(); // Just in case. |
physical_stream_.reset(stream); |
close_timer_.Reset(); |
return true; |
@@ -69,6 +71,7 @@ |
proxy_data->audio_source_callback = callback; |
proxy_data->volume = volume; |
proxy_data->pending_bytes = 0; |
+ proxy_data->prebuffering = true; |
} |
// We cannot start physical stream under the lock, |
// OnMoreData() would try acquiring it... |
@@ -96,8 +99,10 @@ |
} |
} |
if (physical_stream_.get()) { |
- if (stop_physical_stream) |
+ if (stop_physical_stream) { |
physical_stream_->Stop(); |
+ buffer_data_.clear(); // Just in case. |
+ } |
close_timer_.Reset(); |
} |
} |
@@ -155,6 +160,15 @@ |
// at the end. That would speed things up but complicate stopping |
// the stream. |
base::AutoLock lock(lock_); |
+ |
+ // Did we see this buffer before? |
vrk (LEFT CHROMIUM)
2012/04/26 00:54:57
For linux, I believe we will always have a unique
|
+ // If so, get lengths of released data, and delete buffer from the buffer map. |
+ int bytes_released = 0; |
+ BufferMap::iterator it = buffer_data_.find(dest); |
+ if (it != buffer_data_.end()) { |
+ bytes_released = it->second.length; |
+ buffer_data_.erase(it); |
+ } |
if (proxies_.empty()) |
return 0; |
uint32 actual_total_size = 0; |
@@ -169,37 +183,36 @@ |
uint8* actual_dest = dest; |
for (ProxyMap::iterator it = proxies_.begin(); it != proxies_.end(); ++it) { |
ProxyData* proxy_data = &it->second; |
- // TODO(enal): We don't know |pending _bytes| for individual stream, and we |
- // should give that value to individual stream's OnMoreData(). I believe it |
- // can be used there to evaluate exact position of data it should return. |
- // Current code "sorta works" if everything works perfectly, but would have |
- // problems if some of the buffers are only partially filled -- we don't |
- // know how how much data was in the buffer OS returned to us, so we cannot |
- // correctly calculate new value. If we know number of buffers we can solve |
- // the problem by storing not one value but vector of them. |
- int pending_bytes = std::min(proxy_data->pending_bytes, |
- buffers_state.pending_bytes); |
+ |
+ // Handle prebuffering: |
+ // * If we already saw this buffer for this proxy, prebuffering is done, |
+ // proxy now is in the steady state. |
+ // * Otherwise add buffer to the set for this proxy. |
+ if (proxy_data->prebuffering) { |
+ std::set<void*>::iterator it = proxy_data->buffers.find(dest); |
+ if (it != proxy_data->buffers.end()) { |
+ // Release memory used by set, we don't need it anymore. |
+ std::set<void*> empty; |
+ empty.swap(proxy_data->buffers); |
+ proxy_data->prebuffering = false; |
+ } else { |
+ proxy_data->buffers.insert(dest); |
+ } |
+ } |
+ if (!proxy_data->prebuffering) { |
+ proxy_data->pending_bytes -= bytes_released; |
+ DCHECK_GE(proxy_data->pending_bytes, 0); |
+ } |
+ |
// Note: there is no way we can deduce hardware_delay_bytes for the |
// particular proxy stream. Use zero instead. |
uint32 actual_size = proxy_data->audio_source_callback->OnMoreData( |
actual_dest, |
max_size, |
- AudioBuffersState(pending_bytes, 0)); |
- |
- // Should update pending_bytes for each proxy. |
- // If stream ended, pending_bytes goes down by max_size. |
- if (actual_size == 0) { |
- pending_bytes -= max_size; |
- proxy_data->pending_bytes = std::max(pending_bytes, 0); |
+ AudioBuffersState(proxy_data->pending_bytes, 0)); |
+ if (actual_size == 0) |
continue; |
- } |
- // Otherwise, it goes up by amount of data. It cannot exceed max amount of |
- // data we can buffer, but we don't know that value. So we increment |
- // pending_bytes unconditionally but adjust it before actual use (which |
- // would be on a next OnMoreData() call). |
- proxy_data->pending_bytes = pending_bytes + actual_size; |
- |
// No need to mix muted stream. |
double volume = proxy_data->volume; |
if (volume == 0.0) |
@@ -228,6 +241,17 @@ |
actual_total_size = std::max(actual_size, actual_total_size); |
} |
} |
+ |
+ // Now go through all proxies once again and increase pending_bytes |
+ // for each proxy. Could not do it earlier because we did not know |
+ // actual_total_size. |
+ for (ProxyMap::iterator it = proxies_.begin(); it != proxies_.end(); ++it) { |
+ it->second.pending_bytes += actual_total_size; |
+ } |
+ |
+ buffer_data_.insert( |
+ std::pair<void*, BufferData>(dest, BufferData(actual_total_size))); |
+ DCHECK_LE(buffer_data_.size(), 5u); |
return actual_total_size; |
} |