OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | |
7 | 6 |
8 #include <deque> | 7 #include <deque> |
9 #include <vector> | 8 #include <vector> |
10 | 9 |
11 #include "base/bind.h" | 10 #include "base/bind.h" |
12 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
13 #include "base/macros.h" | |
14 #include "base/md5.h" | 12 #include "base/md5.h" |
15 #include "base/message_loop/message_loop.h" | |
16 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
17 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
18 #include "base/sys_byteorder.h" | 15 #include "base/sys_byteorder.h" |
19 #include "build/build_config.h" | 16 #include "build/build_config.h" |
20 #include "media/base/audio_buffer.h" | 17 #include "media/base/audio_buffer.h" |
21 #include "media/base/audio_bus.h" | 18 #include "media/base/audio_bus.h" |
22 #include "media/base/audio_hash.h" | 19 #include "media/base/audio_hash.h" |
23 #include "media/base/decoder_buffer.h" | 20 #include "media/base/decoder_buffer.h" |
24 #include "media/base/media_util.h" | 21 #include "media/base/media_util.h" |
25 #include "media/base/test_data_util.h" | 22 #include "media/base/test_data_util.h" |
26 #include "media/base/test_helpers.h" | 23 #include "media/base/test_helpers.h" |
27 #include "media/base/timestamp_constants.h" | 24 #include "media/base/timestamp_constants.h" |
28 #include "media/ffmpeg/ffmpeg_common.h" | 25 #include "media/ffmpeg/ffmpeg_common.h" |
| 26 #include "media/filters/audio_decoder_test.h" |
29 #include "media/filters/audio_file_reader.h" | 27 #include "media/filters/audio_file_reader.h" |
30 #include "media/filters/ffmpeg_audio_decoder.h" | 28 #include "media/filters/ffmpeg_audio_decoder.h" |
31 #include "media/filters/in_memory_url_protocol.h" | 29 #include "media/filters/in_memory_url_protocol.h" |
32 #include "media/filters/opus_audio_decoder.h" | 30 #include "media/filters/opus_audio_decoder.h" |
33 #include "testing/gtest/include/gtest/gtest.h" | |
34 | 31 |
35 namespace media { | 32 namespace media { |
36 | 33 |
| 34 // AudioDecoderTest implementation. |
| 35 |
37 // The number of packets to read and then decode from each file. | 36 // The number of packets to read and then decode from each file. |
38 static const size_t kDecodeRuns = 3; | 37 static const size_t kDecodeRuns = 3; |
39 static const uint8_t kOpusExtraData[] = { | |
40 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x01, 0x02, | |
41 // The next two bytes represent the codec delay. | |
42 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
43 | |
44 enum AudioDecoderType { | |
45 FFMPEG, | |
46 OPUS, | |
47 }; | |
48 | |
49 struct DecodedBufferExpectations { | |
50 const int64_t timestamp; | |
51 const int64_t duration; | |
52 const char* hash; | |
53 }; | |
54 | |
55 struct DecoderTestData { | |
56 const AudioDecoderType decoder_type; | |
57 const AudioCodec codec; | |
58 const char* filename; | |
59 const DecodedBufferExpectations* expectations; | |
60 const int first_packet_pts; | |
61 const int samples_per_second; | |
62 const ChannelLayout channel_layout; | |
63 }; | |
64 | |
65 // Tells gtest how to print our DecoderTestData structure. | |
66 std::ostream& operator<<(std::ostream& os, const DecoderTestData& data) { | |
67 return os << data.filename; | |
68 } | |
69 | 38 |
70 // Marks negative timestamp buffers for discard or transfers FFmpeg's built in | 39 // Marks negative timestamp buffers for discard or transfers FFmpeg's built in |
71 // discard metadata in favor of setting DiscardPadding on the DecoderBuffer. | 40 // discard metadata in favor of setting DiscardPadding on the DecoderBuffer. |
72 // Allows better testing of AudioDiscardHelper usage. | 41 // Allows better testing of AudioDiscardHelper usage. |
73 static void SetDiscardPadding(AVPacket* packet, | 42 static void SetDiscardPadding(AVPacket* packet, |
74 const scoped_refptr<DecoderBuffer> buffer, | 43 const scoped_refptr<DecoderBuffer> buffer, |
75 double samples_per_second) { | 44 double samples_per_second) { |
76 // Discard negative timestamps. | 45 // Discard negative timestamps. |
77 if (buffer->timestamp() + buffer->duration() < base::TimeDelta()) { | 46 if (buffer->timestamp() + buffer->duration() < base::TimeDelta()) { |
78 buffer->set_discard_padding( | 47 buffer->set_discard_padding( |
(...skipping 12 matching lines...) Expand all Loading... |
91 reinterpret_cast<const uint32_t*>(av_packet_get_side_data( | 60 reinterpret_cast<const uint32_t*>(av_packet_get_side_data( |
92 packet, AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); | 61 packet, AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); |
93 if (skip_samples_size < 4) | 62 if (skip_samples_size < 4) |
94 return; | 63 return; |
95 buffer->set_discard_padding(std::make_pair( | 64 buffer->set_discard_padding(std::make_pair( |
96 base::TimeDelta::FromSecondsD(base::ByteSwapToLE32(*skip_samples_ptr) / | 65 base::TimeDelta::FromSecondsD(base::ByteSwapToLE32(*skip_samples_ptr) / |
97 samples_per_second), | 66 samples_per_second), |
98 base::TimeDelta())); | 67 base::TimeDelta())); |
99 } | 68 } |
100 | 69 |
101 class AudioDecoderTest : public testing::TestWithParam<DecoderTestData> { | 70 AudioDecoderTest::AudioDecoderTest() |
102 public: | 71 : pending_decode_(false), |
103 AudioDecoderTest() | 72 pending_reset_(false), |
104 : pending_decode_(false), | 73 last_decode_status_(AudioDecoder::kDecodeError) { |
105 pending_reset_(false), | 74 switch (GetParam().decoder_type) { |
106 last_decode_status_(AudioDecoder::kDecodeError) { | 75 case FFMPEG: |
107 switch (GetParam().decoder_type) { | 76 decoder_.reset( |
108 case FFMPEG: | 77 new FFmpegAudioDecoder(message_loop_.task_runner(), new MediaLog())); |
109 decoder_.reset(new FFmpegAudioDecoder(message_loop_.task_runner(), | 78 break; |
110 new MediaLog())); | 79 case OPUS: |
111 break; | 80 decoder_.reset(new OpusAudioDecoder(message_loop_.task_runner())); |
112 case OPUS: | 81 break; |
113 decoder_.reset( | |
114 new OpusAudioDecoder(message_loop_.task_runner())); | |
115 break; | |
116 } | |
117 } | 82 } |
| 83 } |
118 | 84 |
119 virtual ~AudioDecoderTest() { | 85 AudioDecoderTest::~AudioDecoderTest() { |
120 EXPECT_FALSE(pending_decode_); | 86 EXPECT_FALSE(pending_decode_); |
121 EXPECT_FALSE(pending_reset_); | 87 EXPECT_FALSE(pending_reset_); |
| 88 } |
| 89 |
| 90 void AudioDecoderTest::DecodeBuffer( |
| 91 const scoped_refptr<DecoderBuffer>& buffer) { |
| 92 ASSERT_FALSE(pending_decode_); |
| 93 pending_decode_ = true; |
| 94 last_decode_status_ = AudioDecoder::kDecodeError; |
| 95 decoder_->Decode(buffer, base::Bind(&AudioDecoderTest::DecodeFinished, |
| 96 base::Unretained(this))); |
| 97 base::RunLoop().RunUntilIdle(); |
| 98 ASSERT_FALSE(pending_decode_); |
| 99 } |
| 100 |
| 101 void AudioDecoderTest::SendEndOfStream() { |
| 102 DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); |
| 103 } |
| 104 |
| 105 void AudioDecoderTest::Initialize() { |
| 106 // Load the test data file. |
| 107 data_ = ReadTestDataFile(GetParam().filename); |
| 108 protocol_.reset( |
| 109 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false)); |
| 110 reader_.reset(new AudioFileReader(protocol_.get())); |
| 111 ASSERT_TRUE(reader_->OpenDemuxerForTesting()); |
| 112 |
| 113 // Load the first packet and check its timestamp. |
| 114 AVPacket packet; |
| 115 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); |
| 116 EXPECT_EQ(GetParam().first_packet_pts, packet.pts); |
| 117 start_timestamp_ = ConvertFromTimeBase( |
| 118 reader_->GetAVStreamForTesting()->time_base, packet.pts); |
| 119 av_packet_unref(&packet); |
| 120 |
| 121 // Seek back to the beginning. |
| 122 ASSERT_TRUE(reader_->SeekForTesting(start_timestamp_)); |
| 123 |
| 124 AudioDecoderConfig config; |
| 125 ASSERT_TRUE(AVCodecContextToAudioDecoderConfig( |
| 126 reader_->codec_context_for_testing(), false, &config)); |
| 127 |
| 128 EXPECT_EQ(GetParam().codec, config.codec()); |
| 129 EXPECT_EQ(GetParam().samples_per_second, config.samples_per_second()); |
| 130 EXPECT_EQ(GetParam().channel_layout, config.channel_layout()); |
| 131 |
| 132 InitializeDecoder(config); |
| 133 } |
| 134 |
| 135 void AudioDecoderTest::InitializeDecoder(const AudioDecoderConfig& config) { |
| 136 InitializeDecoderWithResult(config, true); |
| 137 } |
| 138 |
| 139 void AudioDecoderTest::InitializeDecoderWithResult( |
| 140 const AudioDecoderConfig& config, |
| 141 bool success) { |
| 142 decoder_->Initialize( |
| 143 config, nullptr, NewExpectedBoolCB(success), |
| 144 base::Bind(&AudioDecoderTest::OnDecoderOutput, base::Unretained(this))); |
| 145 base::RunLoop().RunUntilIdle(); |
| 146 } |
| 147 |
| 148 void AudioDecoderTest::Decode() { |
| 149 AVPacket packet; |
| 150 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); |
| 151 |
| 152 // Split out packet metadata before making a copy. |
| 153 av_packet_split_side_data(&packet); |
| 154 |
| 155 scoped_refptr<DecoderBuffer> buffer = |
| 156 DecoderBuffer::CopyFrom(packet.data, packet.size); |
| 157 buffer->set_timestamp(ConvertFromTimeBase( |
| 158 reader_->GetAVStreamForTesting()->time_base, packet.pts)); |
| 159 buffer->set_duration(ConvertFromTimeBase( |
| 160 reader_->GetAVStreamForTesting()->time_base, packet.duration)); |
| 161 if (packet.flags & AV_PKT_FLAG_KEY) |
| 162 buffer->set_is_key_frame(true); |
| 163 |
| 164 // Don't set discard padding for Opus, it already has discard behavior set |
| 165 // based on the codec delay in the AudioDecoderConfig. |
| 166 if (GetParam().decoder_type == FFMPEG) |
| 167 SetDiscardPadding(&packet, buffer, GetParam().samples_per_second); |
| 168 |
| 169 // DecodeBuffer() shouldn't need the original packet since it uses the copy. |
| 170 av_packet_unref(&packet); |
| 171 DecodeBuffer(buffer); |
| 172 } |
| 173 |
| 174 void AudioDecoderTest::Reset() { |
| 175 ASSERT_FALSE(pending_reset_); |
| 176 pending_reset_ = true; |
| 177 decoder_->Reset( |
| 178 base::Bind(&AudioDecoderTest::ResetFinished, base::Unretained(this))); |
| 179 base::RunLoop().RunUntilIdle(); |
| 180 ASSERT_FALSE(pending_reset_); |
| 181 } |
| 182 |
| 183 void AudioDecoderTest::Seek(base::TimeDelta seek_time) { |
| 184 Reset(); |
| 185 decoded_audio_.clear(); |
| 186 ASSERT_TRUE(reader_->SeekForTesting(seek_time)); |
| 187 } |
| 188 |
| 189 void AudioDecoderTest::OnDecoderOutput( |
| 190 const scoped_refptr<AudioBuffer>& buffer) { |
| 191 EXPECT_FALSE(buffer->end_of_stream()); |
| 192 decoded_audio_.push_back(buffer); |
| 193 } |
| 194 |
| 195 void AudioDecoderTest::DecodeFinished(AudioDecoder::Status status) { |
| 196 EXPECT_TRUE(pending_decode_); |
| 197 EXPECT_FALSE(pending_reset_); |
| 198 pending_decode_ = false; |
| 199 last_decode_status_ = status; |
| 200 } |
| 201 |
| 202 void AudioDecoderTest::ResetFinished() { |
| 203 EXPECT_TRUE(pending_reset_); |
| 204 EXPECT_FALSE(pending_decode_); |
| 205 pending_reset_ = false; |
| 206 } |
| 207 |
| 208 // Generates an MD5 hash of the audio signal. Should not be used for checks |
| 209 // across platforms as audio varies slightly across platforms. |
| 210 std::string AudioDecoderTest::GetDecodedAudioMD5(size_t i) { |
| 211 CHECK_LT(i, decoded_audio_.size()); |
| 212 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; |
| 213 |
| 214 scoped_ptr<AudioBus> output = |
| 215 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); |
| 216 buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get()); |
| 217 |
| 218 base::MD5Context context; |
| 219 base::MD5Init(&context); |
| 220 for (int ch = 0; ch < output->channels(); ++ch) { |
| 221 base::MD5Update( |
| 222 &context, |
| 223 base::StringPiece(reinterpret_cast<char*>(output->channel(ch)), |
| 224 output->frames() * sizeof(*output->channel(ch)))); |
122 } | 225 } |
| 226 base::MD5Digest digest; |
| 227 base::MD5Final(&digest, &context); |
| 228 return base::MD5DigestToBase16(digest); |
| 229 } |
123 | 230 |
124 protected: | 231 void AudioDecoderTest::ExpectDecodedAudio(size_t i, |
125 void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer) { | 232 const std::string& exact_hash) { |
126 ASSERT_FALSE(pending_decode_); | 233 CHECK_LT(i, decoded_audio_.size()); |
127 pending_decode_ = true; | 234 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; |
128 last_decode_status_ = AudioDecoder::kDecodeError; | 235 |
129 decoder_->Decode( | 236 const DecodedBufferExpectations& sample_info = GetParam().expectations[i]; |
130 buffer, | 237 EXPECT_EQ(sample_info.timestamp, buffer->timestamp().InMicroseconds()); |
131 base::Bind(&AudioDecoderTest::DecodeFinished, base::Unretained(this))); | 238 EXPECT_EQ(sample_info.duration, buffer->duration().InMicroseconds()); |
132 base::RunLoop().RunUntilIdle(); | 239 EXPECT_FALSE(buffer->end_of_stream()); |
133 ASSERT_FALSE(pending_decode_); | 240 |
| 241 scoped_ptr<AudioBus> output = |
| 242 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); |
| 243 buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get()); |
| 244 |
| 245 // Generate a lossy hash of the audio used for comparison across platforms. |
| 246 AudioHash audio_hash; |
| 247 audio_hash.Update(output.get(), output->frames()); |
| 248 EXPECT_TRUE(audio_hash.IsEquivalent(sample_info.hash, 0.02)) |
| 249 << "Audio hashes differ. Expected: " << sample_info.hash |
| 250 << " Actual: " << audio_hash.ToString(); |
| 251 |
| 252 if (!exact_hash.empty()) { |
| 253 EXPECT_EQ(exact_hash, GetDecodedAudioMD5(i)); |
| 254 |
| 255 // Verify different hashes are being generated. None of our test data |
| 256 // files have audio that hashes out exactly the same. |
| 257 if (i > 0) |
| 258 EXPECT_NE(exact_hash, GetDecodedAudioMD5(i - 1)); |
134 } | 259 } |
| 260 } |
135 | 261 |
136 void SendEndOfStream() { | 262 // Test definitions. |
137 DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); | |
138 } | |
139 | |
140 void Initialize() { | |
141 // Load the test data file. | |
142 data_ = ReadTestDataFile(GetParam().filename); | |
143 protocol_.reset( | |
144 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false)); | |
145 reader_.reset(new AudioFileReader(protocol_.get())); | |
146 ASSERT_TRUE(reader_->OpenDemuxerForTesting()); | |
147 | |
148 // Load the first packet and check its timestamp. | |
149 AVPacket packet; | |
150 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); | |
151 EXPECT_EQ(GetParam().first_packet_pts, packet.pts); | |
152 start_timestamp_ = ConvertFromTimeBase( | |
153 reader_->GetAVStreamForTesting()->time_base, packet.pts); | |
154 av_packet_unref(&packet); | |
155 | |
156 // Seek back to the beginning. | |
157 ASSERT_TRUE(reader_->SeekForTesting(start_timestamp_)); | |
158 | |
159 AudioDecoderConfig config; | |
160 ASSERT_TRUE(AVCodecContextToAudioDecoderConfig( | |
161 reader_->codec_context_for_testing(), false, &config)); | |
162 | |
163 EXPECT_EQ(GetParam().codec, config.codec()); | |
164 EXPECT_EQ(GetParam().samples_per_second, config.samples_per_second()); | |
165 EXPECT_EQ(GetParam().channel_layout, config.channel_layout()); | |
166 | |
167 InitializeDecoder(config); | |
168 } | |
169 | |
170 void InitializeDecoder(const AudioDecoderConfig& config) { | |
171 InitializeDecoderWithResult(config, true); | |
172 } | |
173 | |
174 void InitializeDecoderWithResult(const AudioDecoderConfig& config, | |
175 bool success) { | |
176 decoder_->Initialize( | |
177 config, nullptr, NewExpectedBoolCB(success), | |
178 base::Bind(&AudioDecoderTest::OnDecoderOutput, base::Unretained(this))); | |
179 base::RunLoop().RunUntilIdle(); | |
180 } | |
181 | |
182 void Decode() { | |
183 AVPacket packet; | |
184 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); | |
185 | |
186 // Split out packet metadata before making a copy. | |
187 av_packet_split_side_data(&packet); | |
188 | |
189 scoped_refptr<DecoderBuffer> buffer = | |
190 DecoderBuffer::CopyFrom(packet.data, packet.size); | |
191 buffer->set_timestamp(ConvertFromTimeBase( | |
192 reader_->GetAVStreamForTesting()->time_base, packet.pts)); | |
193 buffer->set_duration(ConvertFromTimeBase( | |
194 reader_->GetAVStreamForTesting()->time_base, packet.duration)); | |
195 if (packet.flags & AV_PKT_FLAG_KEY) | |
196 buffer->set_is_key_frame(true); | |
197 | |
198 // Don't set discard padding for Opus, it already has discard behavior set | |
199 // based on the codec delay in the AudioDecoderConfig. | |
200 if (GetParam().decoder_type == FFMPEG) | |
201 SetDiscardPadding(&packet, buffer, GetParam().samples_per_second); | |
202 | |
203 // DecodeBuffer() shouldn't need the original packet since it uses the copy. | |
204 av_packet_unref(&packet); | |
205 DecodeBuffer(buffer); | |
206 } | |
207 | |
208 void Reset() { | |
209 ASSERT_FALSE(pending_reset_); | |
210 pending_reset_ = true; | |
211 decoder_->Reset( | |
212 base::Bind(&AudioDecoderTest::ResetFinished, base::Unretained(this))); | |
213 base::RunLoop().RunUntilIdle(); | |
214 ASSERT_FALSE(pending_reset_); | |
215 } | |
216 | |
217 void Seek(base::TimeDelta seek_time) { | |
218 Reset(); | |
219 decoded_audio_.clear(); | |
220 ASSERT_TRUE(reader_->SeekForTesting(seek_time)); | |
221 } | |
222 | |
223 void OnDecoderOutput(const scoped_refptr<AudioBuffer>& buffer) { | |
224 EXPECT_FALSE(buffer->end_of_stream()); | |
225 decoded_audio_.push_back(buffer); | |
226 } | |
227 | |
228 void DecodeFinished(AudioDecoder::Status status) { | |
229 EXPECT_TRUE(pending_decode_); | |
230 EXPECT_FALSE(pending_reset_); | |
231 pending_decode_ = false; | |
232 last_decode_status_ = status; | |
233 } | |
234 | |
235 void ResetFinished() { | |
236 EXPECT_TRUE(pending_reset_); | |
237 EXPECT_FALSE(pending_decode_); | |
238 pending_reset_ = false; | |
239 } | |
240 | |
241 // Generates an MD5 hash of the audio signal. Should not be used for checks | |
242 // across platforms as audio varies slightly across platforms. | |
243 std::string GetDecodedAudioMD5(size_t i) { | |
244 CHECK_LT(i, decoded_audio_.size()); | |
245 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; | |
246 | |
247 scoped_ptr<AudioBus> output = | |
248 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); | |
249 buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get()); | |
250 | |
251 base::MD5Context context; | |
252 base::MD5Init(&context); | |
253 for (int ch = 0; ch < output->channels(); ++ch) { | |
254 base::MD5Update( | |
255 &context, | |
256 base::StringPiece(reinterpret_cast<char*>(output->channel(ch)), | |
257 output->frames() * sizeof(*output->channel(ch)))); | |
258 } | |
259 base::MD5Digest digest; | |
260 base::MD5Final(&digest, &context); | |
261 return base::MD5DigestToBase16(digest); | |
262 } | |
263 | |
264 void ExpectDecodedAudio(size_t i, const std::string& exact_hash) { | |
265 CHECK_LT(i, decoded_audio_.size()); | |
266 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; | |
267 | |
268 const DecodedBufferExpectations& sample_info = GetParam().expectations[i]; | |
269 EXPECT_EQ(sample_info.timestamp, buffer->timestamp().InMicroseconds()); | |
270 EXPECT_EQ(sample_info.duration, buffer->duration().InMicroseconds()); | |
271 EXPECT_FALSE(buffer->end_of_stream()); | |
272 | |
273 scoped_ptr<AudioBus> output = | |
274 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); | |
275 buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get()); | |
276 | |
277 // Generate a lossy hash of the audio used for comparison across platforms. | |
278 AudioHash audio_hash; | |
279 audio_hash.Update(output.get(), output->frames()); | |
280 EXPECT_EQ(sample_info.hash, audio_hash.ToString()); | |
281 | |
282 if (!exact_hash.empty()) { | |
283 EXPECT_EQ(exact_hash, GetDecodedAudioMD5(i)); | |
284 | |
285 // Verify different hashes are being generated. None of our test data | |
286 // files have audio that hashes out exactly the same. | |
287 if (i > 0) | |
288 EXPECT_NE(exact_hash, GetDecodedAudioMD5(i - 1)); | |
289 } | |
290 } | |
291 | |
292 size_t decoded_audio_size() const { return decoded_audio_.size(); } | |
293 base::TimeDelta start_timestamp() const { return start_timestamp_; } | |
294 const scoped_refptr<AudioBuffer>& decoded_audio(size_t i) { | |
295 return decoded_audio_[i]; | |
296 } | |
297 AudioDecoder::Status last_decode_status() const { | |
298 return last_decode_status_; | |
299 } | |
300 | |
301 private: | |
302 base::MessageLoop message_loop_; | |
303 scoped_refptr<DecoderBuffer> data_; | |
304 scoped_ptr<InMemoryUrlProtocol> protocol_; | |
305 scoped_ptr<AudioFileReader> reader_; | |
306 | |
307 scoped_ptr<AudioDecoder> decoder_; | |
308 bool pending_decode_; | |
309 bool pending_reset_; | |
310 AudioDecoder::Status last_decode_status_; | |
311 | |
312 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_; | |
313 base::TimeDelta start_timestamp_; | |
314 | |
315 DISALLOW_COPY_AND_ASSIGN(AudioDecoderTest); | |
316 }; | |
317 | |
318 class OpusAudioDecoderBehavioralTest : public AudioDecoderTest {}; | |
319 class FFmpegAudioDecoderBehavioralTest : public AudioDecoderTest {}; | |
320 | 263 |
321 TEST_P(AudioDecoderTest, Initialize) { | 264 TEST_P(AudioDecoderTest, Initialize) { |
322 ASSERT_NO_FATAL_FAILURE(Initialize()); | 265 ASSERT_NO_FATAL_FAILURE(Initialize()); |
323 } | 266 } |
324 | 267 |
325 // Verifies decode audio as well as the Decode() -> Reset() sequence. | 268 // Verifies decode audio as well as the Decode() -> Reset() sequence. |
326 TEST_P(AudioDecoderTest, ProduceAudioSamples) { | 269 TEST_P(AudioDecoderTest, ProduceAudioSamples) { |
327 ASSERT_NO_FATAL_FAILURE(Initialize()); | 270 ASSERT_NO_FATAL_FAILURE(Initialize()); |
328 | 271 |
329 // Run the test multiple times with a seek back to the beginning in between. | 272 // Run the test multiple times with a seek back to the beginning in between. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 } | 314 } |
372 | 315 |
373 TEST_P(AudioDecoderTest, NoTimestamp) { | 316 TEST_P(AudioDecoderTest, NoTimestamp) { |
374 ASSERT_NO_FATAL_FAILURE(Initialize()); | 317 ASSERT_NO_FATAL_FAILURE(Initialize()); |
375 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0)); | 318 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0)); |
376 buffer->set_timestamp(kNoTimestamp()); | 319 buffer->set_timestamp(kNoTimestamp()); |
377 DecodeBuffer(buffer); | 320 DecodeBuffer(buffer); |
378 EXPECT_EQ(AudioDecoder::kDecodeError, last_decode_status()); | 321 EXPECT_EQ(AudioDecoder::kDecodeError, last_decode_status()); |
379 } | 322 } |
380 | 323 |
381 TEST_P(OpusAudioDecoderBehavioralTest, InitializeWithNoCodecDelay) { | |
382 ASSERT_EQ(GetParam().decoder_type, OPUS); | |
383 std::vector<uint8_t> extra_data( | |
384 kOpusExtraData, | |
385 kOpusExtraData + arraysize(kOpusExtraData)); | |
386 AudioDecoderConfig decoder_config; | |
387 decoder_config.Initialize(kCodecOpus, | |
388 kSampleFormatF32, | |
389 CHANNEL_LAYOUT_STEREO, | |
390 48000, | |
391 extra_data, | |
392 false, | |
393 base::TimeDelta::FromMilliseconds(80), | |
394 0); | |
395 InitializeDecoder(decoder_config); | |
396 } | |
397 | |
398 TEST_P(OpusAudioDecoderBehavioralTest, InitializeWithBadCodecDelay) { | |
399 ASSERT_EQ(GetParam().decoder_type, OPUS); | |
400 std::vector<uint8_t> extra_data( | |
401 kOpusExtraData, | |
402 kOpusExtraData + arraysize(kOpusExtraData)); | |
403 AudioDecoderConfig decoder_config; | |
404 decoder_config.Initialize( | |
405 kCodecOpus, | |
406 kSampleFormatF32, | |
407 CHANNEL_LAYOUT_STEREO, | |
408 48000, | |
409 extra_data, | |
410 false, | |
411 base::TimeDelta::FromMilliseconds(80), | |
412 // Use a different codec delay than in the extradata. | |
413 100); | |
414 InitializeDecoderWithResult(decoder_config, true); | |
415 } | |
416 | |
417 #if defined(OPUS_FIXED_POINT) | |
418 const DecodedBufferExpectations kSfxOpusExpectations[] = { | |
419 {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"}, | |
420 {13500, 20000, "5.48,5.93,6.05,5.83,5.54,5.46,"}, | |
421 {33500, 20000, "-3.44,-3.34,-3.57,-4.11,-4.74,-5.13,"}, | |
422 }; | |
423 #else | |
424 const DecodedBufferExpectations kSfxOpusExpectations[] = { | |
425 {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"}, | |
426 {13500, 20000, "5.48,5.93,6.04,5.83,5.54,5.45,"}, | |
427 {33500, 20000, "-3.45,-3.35,-3.57,-4.12,-4.74,-5.14,"}, | |
428 }; | |
429 #endif | |
430 | |
431 const DecodedBufferExpectations kBearOpusExpectations[] = { | |
432 {500, 3500, "-0.26,0.87,1.36,0.84,-0.30,-1.22,"}, | |
433 {4000, 10000, "0.09,0.23,0.21,0.03,-0.17,-0.24,"}, | |
434 {14000, 10000, "0.10,0.24,0.23,0.04,-0.14,-0.23,"}, | |
435 }; | |
436 | |
437 const DecoderTestData kOpusTests[] = { | |
438 {OPUS, kCodecOpus, "sfx-opus.ogg", kSfxOpusExpectations, -312, 48000, | |
439 CHANNEL_LAYOUT_MONO}, | |
440 {OPUS, kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000, | |
441 CHANNEL_LAYOUT_STEREO}, | |
442 }; | |
443 | |
444 // Dummy data for behavioral tests. | |
445 const DecoderTestData kOpusBehavioralTest[] = { | |
446 {OPUS, kUnknownAudioCodec, "", NULL, 0, 0, CHANNEL_LAYOUT_NONE}, | |
447 }; | |
448 | |
449 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderTest, | |
450 AudioDecoderTest, | |
451 testing::ValuesIn(kOpusTests)); | |
452 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderBehavioralTest, | |
453 OpusAudioDecoderBehavioralTest, | |
454 testing::ValuesIn(kOpusBehavioralTest)); | |
455 | |
456 #if defined(USE_PROPRIETARY_CODECS) | |
457 const DecodedBufferExpectations kSfxMp3Expectations[] = { | |
458 {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"}, | |
459 {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"}, | |
460 {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"}, | |
461 }; | |
462 | |
463 const DecodedBufferExpectations kSfxAdtsExpectations[] = { | |
464 {0, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"}, | |
465 {23219, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"}, | |
466 {46439, 23219, "1.42,1.69,2.95,4.23,4.02,2.36,"}, | |
467 }; | |
468 #endif | |
469 | |
470 #if defined(OS_CHROMEOS) | |
471 const DecodedBufferExpectations kSfxFlacExpectations[] = { | |
472 {0, 104489, "-2.42,-1.12,0.71,1.70,1.09,-0.68,"}, | |
473 {104489, 104489, "-1.99,-0.67,1.18,2.19,1.60,-0.16,"}, | |
474 {208979, 79433, "2.84,2.70,3.23,4.06,4.59,4.44,"}, | |
475 }; | |
476 #endif | |
477 | |
478 const DecodedBufferExpectations kSfxWaveExpectations[] = { | |
479 {0, 23219, "-1.23,-0.87,0.47,1.85,1.88,0.29,"}, | |
480 {23219, 23219, "0.75,1.10,2.43,3.78,3.53,1.93,"}, | |
481 {46439, 23219, "1.27,1.56,2.83,4.13,3.87,2.23,"}, | |
482 }; | |
483 | |
484 const DecodedBufferExpectations kFourChannelWaveExpectations[] = { | |
485 {0, 11609, "-1.68,1.68,0.89,-3.45,1.52,1.15,"}, | |
486 {11609, 11609, "43.26,9.06,18.27,35.98,19.45,7.46,"}, | |
487 {23219, 11609, "36.37,9.45,16.04,27.67,18.81,10.15,"}, | |
488 }; | |
489 | |
490 const DecodedBufferExpectations kSfxOggExpectations[] = { | |
491 {0, 13061, "-0.33,1.25,2.86,3.26,2.09,0.14,"}, | |
492 {13061, 23219, "-2.79,-2.42,-1.06,0.33,0.93,-0.64,"}, | |
493 {36281, 23219, "-1.19,-0.80,0.57,1.97,2.08,0.51,"}, | |
494 }; | |
495 | |
496 const DecodedBufferExpectations kBearOgvExpectations[] = { | |
497 {0, 13061, "-1.25,0.10,2.11,2.29,1.50,-0.68,"}, | |
498 {13061, 23219, "-1.80,-1.41,-0.13,1.30,1.65,0.01,"}, | |
499 {36281, 23219, "-1.43,-1.25,0.11,1.29,1.86,0.14,"}, | |
500 }; | |
501 | |
502 const DecoderTestData kFFmpegTests[] = { | |
503 #if defined(USE_PROPRIETARY_CODECS) | |
504 {FFMPEG, kCodecMP3, "sfx.mp3", kSfxMp3Expectations, 0, 44100, | |
505 CHANNEL_LAYOUT_MONO}, | |
506 {FFMPEG, kCodecAAC, "sfx.adts", kSfxAdtsExpectations, 0, 44100, | |
507 CHANNEL_LAYOUT_MONO}, | |
508 #endif | |
509 #if defined(OS_CHROMEOS) | |
510 {FFMPEG, kCodecFLAC, "sfx.flac", kSfxFlacExpectations, 0, 44100, | |
511 CHANNEL_LAYOUT_MONO}, | |
512 #endif | |
513 {FFMPEG, kCodecPCM, "sfx_f32le.wav", kSfxWaveExpectations, 0, 44100, | |
514 CHANNEL_LAYOUT_MONO}, | |
515 {FFMPEG, kCodecPCM, "4ch.wav", kFourChannelWaveExpectations, 0, 44100, | |
516 CHANNEL_LAYOUT_QUAD}, | |
517 {FFMPEG, kCodecVorbis, "sfx.ogg", kSfxOggExpectations, 0, 44100, | |
518 CHANNEL_LAYOUT_MONO}, | |
519 // Note: bear.ogv is incorrectly muxed such that valid samples are given | |
520 // negative timestamps, this marks them for discard per the ogg vorbis spec. | |
521 {FFMPEG, kCodecVorbis, "bear.ogv", kBearOgvExpectations, -704, 44100, | |
522 CHANNEL_LAYOUT_STEREO}, | |
523 }; | |
524 | |
525 // Dummy data for behavioral tests. | |
526 const DecoderTestData kFFmpegBehavioralTest[] = { | |
527 {FFMPEG, kUnknownAudioCodec, "", NULL, 0, 0, CHANNEL_LAYOUT_NONE}, | |
528 }; | |
529 | |
530 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderTest, | |
531 AudioDecoderTest, | |
532 testing::ValuesIn(kFFmpegTests)); | |
533 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderBehavioralTest, | |
534 FFmpegAudioDecoderBehavioralTest, | |
535 testing::ValuesIn(kFFmpegBehavioralTest)); | |
536 | |
537 } // namespace media | 324 } // namespace media |
OLD | NEW |