diff options
author | dalecurtis@google.com <dalecurtis@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-01 23:22:14 +0000 |
---|---|---|
committer | dalecurtis@google.com <dalecurtis@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-01 23:22:14 +0000 |
commit | 532f5ce2dad3f5b49166ec0a21a7f9d875605bdb (patch) | |
tree | e0d54371949f055c642b41ccc30c30a4e8d07036 /media/audio/null_audio_sink.cc | |
parent | 5252c891ca0f5e1fad81adcd86d7889ecf0abc9f (diff) | |
download | chromium_src-532f5ce2dad3f5b49166ec0a21a7f9d875605bdb.zip chromium_src-532f5ce2dad3f5b49166ec0a21a7f9d875605bdb.tar.gz chromium_src-532f5ce2dad3f5b49166ec0a21a7f9d875605bdb.tar.bz2 |
Fix audio hashing. Split hash tests out of normal test.
The previous hashing code didn't work for a few reasons:
- Underflow situations (valgrind, etc) would result in different
hashes due to silence we output during underflow.
- Hashing was endian specific, so tests would fail on ARM.
- Each FillBufferTask hashed all the audio data for all channels
each time, which breaks when frames_recieved varies under load.
The above have been fixed:
- Hash tests are split out into new BasicPlaybackHashed test.
- Underflow is now disabled for audio hash testing.
- Hashes are computed in little-endian byte order.
- A separate hash context is maintained for each channel and only
reduced to a single hash at the end.
BUG=129284
TEST=media_unittests under valgrind/tsan.
Review URL: https://chromiumcodereview.appspot.com/10444120
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140123 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/null_audio_sink.cc')
-rw-r--r-- | media/audio/null_audio_sink.cc | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc index b6a921c..b2674fb 100644 --- a/media/audio/null_audio_sink.cc +++ b/media/audio/null_audio_sink.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/stringprintf.h" +#include "base/sys_byteorder.h" #include "base/threading/platform_thread.h" namespace media { @@ -30,6 +31,12 @@ void NullAudioSink::Initialize(const AudioParameters& params, audio_data_.push_back(channel_data); } + if (hash_audio_for_testing_) { + md5_channel_contexts_.reset(new base::MD5Context[params.channels()]); + for (int i = 0; i < params.channels(); i++) + base::MD5Init(&md5_channel_contexts_[i]); + } + callback_ = callback; initialized_ = true; } @@ -93,15 +100,18 @@ void NullAudioSink::FillBufferTask() { int frames_per_millisecond = params_.sample_rate() / base::Time::kMillisecondsPerSecond; - if (hash_audio_for_testing_) { + if (hash_audio_for_testing_ && frames_received > 0) { + DCHECK_EQ(sizeof(float), sizeof(uint32)); int channels = audio_data_.size(); - // Include hash of channel count in case frames_received == 0. - base::MD5Update(&md5_context_, base::StringPiece( - base::StringPrintf("%d", channels))); - for (int channel_index = 0; channel_index < channels; ++channel_index) { - base::MD5Update(&md5_context_, base::StringPiece( - reinterpret_cast<char*>(audio_data_[channel_index]), - sizeof(float) * frames_received)); + for (int channel_idx = 0; channel_idx < channels; ++channel_idx) { + for (int frame_idx = 0; frame_idx < frames_received; frame_idx++) { + // Convert float to uint32 w/o conversion loss. + uint32 frame = base::ByteSwapToLE32(*reinterpret_cast<uint32*>( + &audio_data_[channel_idx][frame_idx])); + base::MD5Update( + &md5_channel_contexts_[channel_idx], base::StringPiece( + reinterpret_cast<char*>(&frame), sizeof(frame))); + } } } @@ -121,14 +131,22 @@ void NullAudioSink::FillBufferTask() { } void NullAudioSink::StartAudioHashForTesting() { + DCHECK(!initialized_); hash_audio_for_testing_ = true; - base::MD5Init(&md5_context_); } std::string NullAudioSink::GetAudioHashForTesting() { DCHECK(hash_audio_for_testing_); + + // Hash all channels into the first channel. base::MD5Digest digest; - base::MD5Final(&digest, &md5_context_); + for (size_t i = 1; i < audio_data_.size(); i++) { + base::MD5Final(&digest, &md5_channel_contexts_[i]); + base::MD5Update(&md5_channel_contexts_[0], base::StringPiece( + reinterpret_cast<char*>(&digest), sizeof(base::MD5Digest))); + } + + base::MD5Final(&digest, &md5_channel_contexts_[0]); return base::MD5DigestToBase16(digest); } |