| Index: media/audio/audio_output_mixer.cc
|
| ===================================================================
|
| --- media/audio/audio_output_mixer.cc (revision 133745)
|
| +++ media/audio/audio_output_mixer.cc (working copy)
|
| @@ -24,7 +24,8 @@
|
| close_timer_(FROM_HERE,
|
| close_delay,
|
| weak_this_.GetWeakPtr(),
|
| - &AudioOutputMixer::ClosePhysicalStream) {
|
| + &AudioOutputMixer::ClosePhysicalStream),
|
| + pending_bytes_(0) {
|
| // TODO(enal): align data.
|
| mixer_data_.reset(new uint8[params_.GetBytesPerBuffer()]);
|
| }
|
| @@ -44,6 +45,7 @@
|
| stream->Close();
|
| return false;
|
| }
|
| + pending_bytes_ = 0; // Just in case.
|
| physical_stream_.reset(stream);
|
| close_timer_.Reset();
|
| return true;
|
| @@ -96,8 +98,10 @@
|
| }
|
| }
|
| if (physical_stream_.get()) {
|
| - if (stop_physical_stream)
|
| + if (stop_physical_stream) {
|
| physical_stream_->Stop();
|
| + pending_bytes_ = 0; // Just in case.
|
| + }
|
| close_timer_.Reset();
|
| }
|
| }
|
| @@ -155,8 +159,12 @@
|
| // at the end. That would speed things up but complicate stopping
|
| // the stream.
|
| base::AutoLock lock(lock_);
|
| - if (proxies_.empty())
|
| +
|
| + DCHECK_GE(pending_bytes_, buffers_state.pending_bytes);
|
| + if (proxies_.empty()) {
|
| + pending_bytes_ = buffers_state.pending_bytes;
|
| return 0;
|
| + }
|
| uint32 actual_total_size = 0;
|
| uint32 bytes_per_sample = params_.bits_per_sample() >> 3;
|
|
|
| @@ -169,37 +177,24 @@
|
| 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);
|
| +
|
| + // If proxy's pending bytes are the same as pending bytes for combined
|
| + // stream, both are either pre-buffering or in the steady state. In either
|
| + // case new pending bytes for proxy is the same as new pending bytes for
|
| + // combined stream.
|
| + // Note: use >= instead of ==, that way is safer.
|
| + if (proxy_data->pending_bytes >= pending_bytes_)
|
| + proxy_data->pending_bytes = buffers_state.pending_bytes;
|
| +
|
| // 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 +223,15 @@
|
| 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;
|
| + }
|
| + pending_bytes_ = buffers_state.pending_bytes + actual_total_size;
|
| +
|
| return actual_total_size;
|
| }
|
|
|
|
|