Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: media/filters/audio_decoder_unittest.cc

Issue 2642823004: media: Fix MediaCodecAudioDecoder reinitialization (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/android/media_codec_audio_decoder.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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> 6 #include <stdint.h>
7 7
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 18 matching lines...) Expand all
29 #include "media/filters/audio_file_reader.h" 29 #include "media/filters/audio_file_reader.h"
30 #include "media/filters/ffmpeg_audio_decoder.h" 30 #include "media/filters/ffmpeg_audio_decoder.h"
31 #include "media/filters/in_memory_url_protocol.h" 31 #include "media/filters/in_memory_url_protocol.h"
32 #include "media/media_features.h" 32 #include "media/media_features.h"
33 #include "testing/gtest/include/gtest/gtest.h" 33 #include "testing/gtest/include/gtest/gtest.h"
34 34
35 #if defined(OS_ANDROID) 35 #if defined(OS_ANDROID)
36 #include "base/android/build_info.h" 36 #include "base/android/build_info.h"
37 #include "media/base/android/media_codec_util.h" 37 #include "media/base/android/media_codec_util.h"
38 #include "media/filters/android/media_codec_audio_decoder.h" 38 #include "media/filters/android/media_codec_audio_decoder.h"
39 #endif
39 40
40 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 41 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
41 #include "media/formats/mpeg/adts_stream_parser.h" 42 #include "media/formats/mpeg/adts_stream_parser.h"
42 #endif 43 #endif
43 44
44 // Helper macro to skip the test if MediaCodec is not available. 45 using testing::Combine;
45 #define SKIP_TEST_IF_NO_MEDIA_CODEC() \ 46 using testing::TestWithParam;
46 do { \ 47 using testing::Values;
47 if (GetParam().decoder_type == MEDIA_CODEC) { \ 48 using testing::ValuesIn;
48 if (!MediaCodecUtil::IsMediaCodecAvailable()) { \
49 VLOG(0) << "Could not run test - no MediaCodec on device."; \
50 return; \
51 } \
52 if (GetParam().codec == kCodecOpus && \
53 base::android::BuildInfo::GetInstance()->sdk_int() < 21) { \
54 VLOG(0) << "Could not run test - Opus is not supported"; \
55 return; \
56 } \
57 } \
58 } while (0)
59 #else
60 #define SKIP_TEST_IF_NO_MEDIA_CODEC() \
61 do { \
62 } while (0)
63 #endif // !defined(OS_ANDROID)
64 49
65 namespace media { 50 namespace media {
66 51
52 namespace {
53
54 #define SKIP_TEST_IF_NOT_SUPPORTED() \
55 do { \
56 if (!IsSupported()) \
57 return; \
58 } while (0)
59
67 // The number of packets to read and then decode from each file. 60 // The number of packets to read and then decode from each file.
68 static const size_t kDecodeRuns = 3; 61 const size_t kDecodeRuns = 3;
69 62
70 enum AudioDecoderType { 63 enum AudioDecoderType {
71 FFMPEG, 64 FFMPEG,
72 #if defined(OS_ANDROID) 65 #if defined(OS_ANDROID)
73 MEDIA_CODEC, 66 MEDIA_CODEC,
74 #endif 67 #endif
75 }; 68 };
76 69
77 struct DecodedBufferExpectations { 70 struct DecodedBufferExpectations {
78 const int64_t timestamp; 71 int64_t timestamp;
79 const int64_t duration; 72 int64_t duration;
80 const char* hash; 73 const char* hash;
81 }; 74 };
82 75
83 struct DecoderTestData { 76 struct TestParams {
84 const AudioDecoderType decoder_type; 77 AudioCodec codec;
85 const AudioCodec codec;
86 const char* filename; 78 const char* filename;
87 const DecodedBufferExpectations* expectations; 79 const DecodedBufferExpectations* expectations;
88 const int first_packet_pts; 80 int first_packet_pts;
89 const int samples_per_second; 81 int samples_per_second;
90 const ChannelLayout channel_layout; 82 ChannelLayout channel_layout;
91 }; 83 };
92 84
93 // Tells gtest how to print our DecoderTestData structure. 85 // Tells gtest how to print our TestParams structure.
94 std::ostream& operator<<(std::ostream& os, const DecoderTestData& data) { 86 std::ostream& operator<<(std::ostream& os, const TestParams& params) {
95 return os << data.filename; 87 return os << params.filename;
96 } 88 }
97 89
98 // Marks negative timestamp buffers for discard or transfers FFmpeg's built in 90 // Marks negative timestamp buffers for discard or transfers FFmpeg's built in
99 // discard metadata in favor of setting DiscardPadding on the DecoderBuffer. 91 // discard metadata in favor of setting DiscardPadding on the DecoderBuffer.
100 // Allows better testing of AudioDiscardHelper usage. 92 // Allows better testing of AudioDiscardHelper usage.
101 static void SetDiscardPadding(AVPacket* packet, 93 void SetDiscardPadding(AVPacket* packet,
102 const scoped_refptr<DecoderBuffer> buffer, 94 const scoped_refptr<DecoderBuffer> buffer,
103 double samples_per_second) { 95 double samples_per_second) {
104 // Discard negative timestamps. 96 // Discard negative timestamps.
105 if (buffer->timestamp() + buffer->duration() < base::TimeDelta()) { 97 if (buffer->timestamp() + buffer->duration() < base::TimeDelta()) {
106 buffer->set_discard_padding( 98 buffer->set_discard_padding(
107 std::make_pair(kInfiniteDuration, base::TimeDelta())); 99 std::make_pair(kInfiniteDuration, base::TimeDelta()));
108 return; 100 return;
109 } 101 }
110 if (buffer->timestamp() < base::TimeDelta()) { 102 if (buffer->timestamp() < base::TimeDelta()) {
111 buffer->set_discard_padding( 103 buffer->set_discard_padding(
112 std::make_pair(-buffer->timestamp(), base::TimeDelta())); 104 std::make_pair(-buffer->timestamp(), base::TimeDelta()));
113 return; 105 return;
114 } 106 }
115 107
116 // If the timestamp is positive, try to use FFmpeg's discard data. 108 // If the timestamp is positive, try to use FFmpeg's discard data.
117 int skip_samples_size = 0; 109 int skip_samples_size = 0;
118 const uint32_t* skip_samples_ptr = 110 const uint32_t* skip_samples_ptr =
119 reinterpret_cast<const uint32_t*>(av_packet_get_side_data( 111 reinterpret_cast<const uint32_t*>(av_packet_get_side_data(
120 packet, AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); 112 packet, AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size));
121 if (skip_samples_size < 4) 113 if (skip_samples_size < 4)
122 return; 114 return;
123 buffer->set_discard_padding(std::make_pair( 115 buffer->set_discard_padding(std::make_pair(
124 base::TimeDelta::FromSecondsD(base::ByteSwapToLE32(*skip_samples_ptr) / 116 base::TimeDelta::FromSecondsD(base::ByteSwapToLE32(*skip_samples_ptr) /
125 samples_per_second), 117 samples_per_second),
126 base::TimeDelta())); 118 base::TimeDelta()));
127 } 119 }
128 120
129 class AudioDecoderTest : public testing::TestWithParam<DecoderTestData> { 121 } // namespace
122
123 class AudioDecoderTest
124 : public TestWithParam<std::tuple<AudioDecoderType, TestParams>> {
130 public: 125 public:
131 AudioDecoderTest() 126 AudioDecoderTest()
132 : pending_decode_(false), 127 : decoder_type_(std::get<0>(GetParam())),
128 params_(std::get<1>(GetParam())),
129 pending_decode_(false),
133 pending_reset_(false), 130 pending_reset_(false),
134 last_decode_status_(DecodeStatus::DECODE_ERROR) { 131 last_decode_status_(DecodeStatus::DECODE_ERROR) {
135 switch (GetParam().decoder_type) { 132 switch (decoder_type_) {
136 case FFMPEG: 133 case FFMPEG:
137 decoder_.reset(new FFmpegAudioDecoder(message_loop_.task_runner(), 134 decoder_.reset(new FFmpegAudioDecoder(message_loop_.task_runner(),
138 new MediaLog())); 135 new MediaLog()));
139 break; 136 break;
140 #if defined(OS_ANDROID) 137 #if defined(OS_ANDROID)
141 case MEDIA_CODEC: 138 case MEDIA_CODEC:
142 decoder_.reset(new MediaCodecAudioDecoder(message_loop_.task_runner())); 139 decoder_.reset(new MediaCodecAudioDecoder(message_loop_.task_runner()));
143 break; 140 break;
144 #endif 141 #endif
145 } 142 }
146 } 143 }
147 144
148 virtual ~AudioDecoderTest() { 145 virtual ~AudioDecoderTest() {
149 EXPECT_FALSE(pending_decode_); 146 EXPECT_FALSE(pending_decode_);
150 EXPECT_FALSE(pending_reset_); 147 EXPECT_FALSE(pending_reset_);
151 } 148 }
152 149
153 protected: 150 protected:
151 bool IsSupported() const {
152 #if defined(OS_ANDROID)
153 if (decoder_type_ == MEDIA_CODEC) {
154 if (!MediaCodecUtil::IsMediaCodecAvailable()) {
155 VLOG(0) << "Could not run test - no MediaCodec on device.";
156 return false;
157 }
158 if (params_.codec == kCodecOpus &&
159 base::android::BuildInfo::GetInstance()->sdk_int() < 21) {
160 VLOG(0) << "Could not run test - Opus is not supported";
161 return false;
162 }
163 }
164 #endif
165 return true;
166 }
167
154 void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer) { 168 void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer) {
155 ASSERT_FALSE(pending_decode_); 169 ASSERT_FALSE(pending_decode_);
156 pending_decode_ = true; 170 pending_decode_ = true;
157 last_decode_status_ = DecodeStatus::DECODE_ERROR; 171 last_decode_status_ = DecodeStatus::DECODE_ERROR;
158 172
159 base::RunLoop run_loop; 173 base::RunLoop run_loop;
160 decoder_->Decode( 174 decoder_->Decode(
161 buffer, base::Bind(&AudioDecoderTest::DecodeFinished, 175 buffer, base::Bind(&AudioDecoderTest::DecodeFinished,
162 base::Unretained(this), run_loop.QuitClosure())); 176 base::Unretained(this), run_loop.QuitClosure()));
163 run_loop.Run(); 177 run_loop.Run();
164 ASSERT_FALSE(pending_decode_); 178 ASSERT_FALSE(pending_decode_);
165 } 179 }
166 180
167 void SendEndOfStream() { DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); } 181 void SendEndOfStream() { DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); }
168 182
183 // Set the TestParams explicitly. Can be use to reinitialize the decoder with
184 // different TestParams.
185 void set_params(const TestParams& params) { params_ = params; }
186
169 void Initialize() { 187 void Initialize() {
170 // Load the test data file. 188 // Load the test data file.
171 data_ = ReadTestDataFile(GetParam().filename); 189 data_ = ReadTestDataFile(params_.filename);
172 protocol_.reset( 190 protocol_.reset(
173 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false)); 191 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false));
174 reader_.reset(new AudioFileReader(protocol_.get())); 192 reader_.reset(new AudioFileReader(protocol_.get()));
175 ASSERT_TRUE(reader_->OpenDemuxerForTesting()); 193 ASSERT_TRUE(reader_->OpenDemuxerForTesting());
176 194
177 // Load the first packet and check its timestamp. 195 // Load the first packet and check its timestamp.
178 AVPacket packet; 196 AVPacket packet;
179 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); 197 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet));
180 EXPECT_EQ(GetParam().first_packet_pts, packet.pts); 198 EXPECT_EQ(params_.first_packet_pts, packet.pts);
181 start_timestamp_ = ConvertFromTimeBase( 199 start_timestamp_ = ConvertFromTimeBase(
182 reader_->GetAVStreamForTesting()->time_base, packet.pts); 200 reader_->GetAVStreamForTesting()->time_base, packet.pts);
183 201
184 // Seek back to the beginning. 202 // Seek back to the beginning.
185 ASSERT_TRUE(reader_->SeekForTesting(start_timestamp_)); 203 ASSERT_TRUE(reader_->SeekForTesting(start_timestamp_));
186 204
187 AudioDecoderConfig config; 205 AudioDecoderConfig config;
188 ASSERT_TRUE(AVCodecContextToAudioDecoderConfig( 206 ASSERT_TRUE(AVCodecContextToAudioDecoderConfig(
189 reader_->codec_context_for_testing(), Unencrypted(), &config)); 207 reader_->codec_context_for_testing(), Unencrypted(), &config));
190 208
191 #if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS) 209 #if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
192 // MEDIA_CODEC type requires config->extra_data() for AAC codec. For ADTS 210 // MEDIA_CODEC type requires config->extra_data() for AAC codec. For ADTS
193 // streams we need to extract it with a separate procedure. 211 // streams we need to extract it with a separate procedure.
194 if (GetParam().decoder_type == MEDIA_CODEC && 212 if (decoder_type_ == MEDIA_CODEC && params_.codec == kCodecAAC &&
195 GetParam().codec == kCodecAAC && config.extra_data().empty()) { 213 config.extra_data().empty()) {
196 int sample_rate; 214 int sample_rate;
197 ChannelLayout channel_layout; 215 ChannelLayout channel_layout;
198 std::vector<uint8_t> extra_data; 216 std::vector<uint8_t> extra_data;
199 ASSERT_GT(ADTSStreamParser().ParseFrameHeader( 217 ASSERT_GT(ADTSStreamParser().ParseFrameHeader(
200 packet.data, packet.size, nullptr, &sample_rate, 218 packet.data, packet.size, nullptr, &sample_rate,
201 &channel_layout, nullptr, nullptr, &extra_data), 219 &channel_layout, nullptr, nullptr, &extra_data),
202 0); 220 0);
203 config.Initialize(kCodecAAC, kSampleFormatS16, channel_layout, 221 config.Initialize(kCodecAAC, kSampleFormatS16, channel_layout,
204 sample_rate, extra_data, Unencrypted(), 222 sample_rate, extra_data, Unencrypted(),
205 base::TimeDelta(), 0); 223 base::TimeDelta(), 0);
206 ASSERT_FALSE(config.extra_data().empty()); 224 ASSERT_FALSE(config.extra_data().empty());
207 } 225 }
208 #endif 226 #endif
209 227
210 av_packet_unref(&packet); 228 av_packet_unref(&packet);
211 229
212 EXPECT_EQ(GetParam().codec, config.codec()); 230 EXPECT_EQ(params_.codec, config.codec());
213 EXPECT_EQ(GetParam().samples_per_second, config.samples_per_second()); 231 EXPECT_EQ(params_.samples_per_second, config.samples_per_second());
214 EXPECT_EQ(GetParam().channel_layout, config.channel_layout()); 232 EXPECT_EQ(params_.channel_layout, config.channel_layout());
215 233
216 InitializeDecoder(config); 234 InitializeDecoder(config);
217 } 235 }
218 236
219 void InitializeDecoder(const AudioDecoderConfig& config) { 237 void InitializeDecoder(const AudioDecoderConfig& config) {
220 InitializeDecoderWithResult(config, true); 238 InitializeDecoderWithResult(config, true);
221 } 239 }
222 240
223 void InitializeDecoderWithResult(const AudioDecoderConfig& config, 241 void InitializeDecoderWithResult(const AudioDecoderConfig& config,
224 bool success) { 242 bool success) {
(...skipping 14 matching lines...) Expand all
239 DecoderBuffer::CopyFrom(packet.data, packet.size); 257 DecoderBuffer::CopyFrom(packet.data, packet.size);
240 buffer->set_timestamp(ConvertFromTimeBase( 258 buffer->set_timestamp(ConvertFromTimeBase(
241 reader_->GetAVStreamForTesting()->time_base, packet.pts)); 259 reader_->GetAVStreamForTesting()->time_base, packet.pts));
242 buffer->set_duration(ConvertFromTimeBase( 260 buffer->set_duration(ConvertFromTimeBase(
243 reader_->GetAVStreamForTesting()->time_base, packet.duration)); 261 reader_->GetAVStreamForTesting()->time_base, packet.duration));
244 if (packet.flags & AV_PKT_FLAG_KEY) 262 if (packet.flags & AV_PKT_FLAG_KEY)
245 buffer->set_is_key_frame(true); 263 buffer->set_is_key_frame(true);
246 264
247 // Don't set discard padding for Opus, it already has discard behavior set 265 // Don't set discard padding for Opus, it already has discard behavior set
248 // based on the codec delay in the AudioDecoderConfig. 266 // based on the codec delay in the AudioDecoderConfig.
249 if (GetParam().decoder_type == FFMPEG && GetParam().codec != kCodecOpus) 267 if (decoder_type_ == FFMPEG && params_.codec != kCodecOpus)
250 SetDiscardPadding(&packet, buffer, GetParam().samples_per_second); 268 SetDiscardPadding(&packet, buffer, params_.samples_per_second);
251 269
252 // DecodeBuffer() shouldn't need the original packet since it uses the copy. 270 // DecodeBuffer() shouldn't need the original packet since it uses the copy.
253 av_packet_unref(&packet); 271 av_packet_unref(&packet);
254 DecodeBuffer(buffer); 272 DecodeBuffer(buffer);
255 } 273 }
256 274
257 void Reset() { 275 void Reset() {
258 ASSERT_FALSE(pending_reset_); 276 ASSERT_FALSE(pending_reset_);
259 pending_reset_ = true; 277 pending_reset_ = true;
260 decoder_->Reset( 278 decoder_->Reset(
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 base::MD5Digest digest; 327 base::MD5Digest digest;
310 base::MD5Final(&digest, &context); 328 base::MD5Final(&digest, &context);
311 return base::MD5DigestToBase16(digest); 329 return base::MD5DigestToBase16(digest);
312 } 330 }
313 331
314 // Android MediaCodec returns wrong timestamps (shifted one frame forward) 332 // Android MediaCodec returns wrong timestamps (shifted one frame forward)
315 // for AAC before Android L. Skip the timestamp check in this situation. 333 // for AAC before Android L. Skip the timestamp check in this situation.
316 bool SkipBufferTimestampCheck() const { 334 bool SkipBufferTimestampCheck() const {
317 #if defined(OS_ANDROID) 335 #if defined(OS_ANDROID)
318 return (base::android::BuildInfo::GetInstance()->sdk_int() < 21) && 336 return (base::android::BuildInfo::GetInstance()->sdk_int() < 21) &&
319 GetParam().decoder_type == MEDIA_CODEC && 337 decoder_type_ == MEDIA_CODEC && params_.codec == kCodecAAC;
320 GetParam().codec == kCodecAAC;
321 #else 338 #else
322 return false; 339 return false;
323 #endif 340 #endif
324 } 341 }
325 342
326 void ExpectDecodedAudio(size_t i, const std::string& exact_hash) { 343 void ExpectDecodedAudio(size_t i, const std::string& exact_hash) {
327 CHECK_LT(i, decoded_audio_.size()); 344 CHECK_LT(i, decoded_audio_.size());
328 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; 345 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i];
329 346
330 const DecodedBufferExpectations& sample_info = GetParam().expectations[i]; 347 const DecodedBufferExpectations& sample_info = params_.expectations[i];
331 348
332 // Android MediaCodec returns wrong timestamps (shifted one frame forward) 349 // Android MediaCodec returns wrong timestamps (shifted one frame forward)
333 // for AAC before Android L. Ignore sample_info.timestamp in this situation. 350 // for AAC before Android L. Ignore sample_info.timestamp in this situation.
334 if (!SkipBufferTimestampCheck()) 351 if (!SkipBufferTimestampCheck())
335 EXPECT_EQ(sample_info.timestamp, buffer->timestamp().InMicroseconds()); 352 EXPECT_EQ(sample_info.timestamp, buffer->timestamp().InMicroseconds());
336 EXPECT_EQ(sample_info.duration, buffer->duration().InMicroseconds()); 353 EXPECT_EQ(sample_info.duration, buffer->duration().InMicroseconds());
337 EXPECT_FALSE(buffer->end_of_stream()); 354 EXPECT_FALSE(buffer->end_of_stream());
338 355
339 std::unique_ptr<AudioBus> output = 356 std::unique_ptr<AudioBus> output =
340 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); 357 AudioBus::Create(buffer->channel_count(), buffer->frame_count());
(...skipping 17 matching lines...) Expand all
358 } 375 }
359 376
360 size_t decoded_audio_size() const { return decoded_audio_.size(); } 377 size_t decoded_audio_size() const { return decoded_audio_.size(); }
361 base::TimeDelta start_timestamp() const { return start_timestamp_; } 378 base::TimeDelta start_timestamp() const { return start_timestamp_; }
362 const scoped_refptr<AudioBuffer>& decoded_audio(size_t i) { 379 const scoped_refptr<AudioBuffer>& decoded_audio(size_t i) {
363 return decoded_audio_[i]; 380 return decoded_audio_[i];
364 } 381 }
365 DecodeStatus last_decode_status() const { return last_decode_status_; } 382 DecodeStatus last_decode_status() const { return last_decode_status_; }
366 383
367 private: 384 private:
385 const AudioDecoderType decoder_type_;
386
387 // Current TestParams used to initialize the test and decoder. The initial
388 // valie is std::get<1>(GetParam()). Could be overridden by set_param() so
389 // that the decoder can be reinitialized with different parameters.
390 TestParams params_;
391
368 base::MessageLoop message_loop_; 392 base::MessageLoop message_loop_;
393
369 scoped_refptr<DecoderBuffer> data_; 394 scoped_refptr<DecoderBuffer> data_;
370 std::unique_ptr<InMemoryUrlProtocol> protocol_; 395 std::unique_ptr<InMemoryUrlProtocol> protocol_;
371 std::unique_ptr<AudioFileReader> reader_; 396 std::unique_ptr<AudioFileReader> reader_;
372 397
373 std::unique_ptr<AudioDecoder> decoder_; 398 std::unique_ptr<AudioDecoder> decoder_;
374 bool pending_decode_; 399 bool pending_decode_;
375 bool pending_reset_; 400 bool pending_reset_;
376 DecodeStatus last_decode_status_; 401 DecodeStatus last_decode_status_;
377 402
378 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_; 403 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
379 base::TimeDelta start_timestamp_; 404 base::TimeDelta start_timestamp_;
380 405
381 DISALLOW_COPY_AND_ASSIGN(AudioDecoderTest); 406 DISALLOW_COPY_AND_ASSIGN(AudioDecoderTest);
382 }; 407 };
383 408
384 TEST_P(AudioDecoderTest, Initialize) {
385 SKIP_TEST_IF_NO_MEDIA_CODEC();
386 ASSERT_NO_FATAL_FAILURE(Initialize());
387 }
388
389 // Verifies decode audio as well as the Decode() -> Reset() sequence.
390 TEST_P(AudioDecoderTest, ProduceAudioSamples) {
391 SKIP_TEST_IF_NO_MEDIA_CODEC();
392 ASSERT_NO_FATAL_FAILURE(Initialize());
393
394 // Run the test multiple times with a seek back to the beginning in between.
395 std::vector<std::string> decoded_audio_md5_hashes;
396 for (int i = 0; i < 2; ++i) {
397 // Run decoder until we get at least |kDecodeRuns| output buffers.
398 // Keeping Decode() in a loop seems to be the simplest way to guarantee that
399 // the predefined number of output buffers are produced without draining
400 // (i.e. decoding EOS).
401 do {
402 Decode();
403 ASSERT_EQ(last_decode_status(), DecodeStatus::OK);
404 } while (decoded_audio_size() < kDecodeRuns);
405
406 // With MediaCodecAudioDecoder the output buffers might appear after
407 // some delay. Since we keep decoding in a loop, the number of output
408 // buffers when they eventually appear might exceed |kDecodeRuns|.
409 ASSERT_LE(kDecodeRuns, decoded_audio_size());
410
411 // On the first pass record the exact MD5 hash for each decoded buffer.
412 if (i == 0) {
413 for (size_t j = 0; j < kDecodeRuns; ++j)
414 decoded_audio_md5_hashes.push_back(GetDecodedAudioMD5(j));
415 }
416
417 // On the first pass verify the basic audio hash and sample info. On the
418 // second, verify the exact MD5 sum for each packet. It shouldn't change.
419 for (size_t j = 0; j < kDecodeRuns; ++j) {
420 SCOPED_TRACE(base::StringPrintf("i = %d, j = %" PRIuS, i, j));
421 ExpectDecodedAudio(j, i == 0 ? "" : decoded_audio_md5_hashes[j]);
422 }
423
424 SendEndOfStream();
425
426 // Seek back to the beginning. Calls Reset() on the decoder.
427 Seek(start_timestamp());
428 }
429 }
430
431 TEST_P(AudioDecoderTest, Decode) {
432 SKIP_TEST_IF_NO_MEDIA_CODEC();
433 ASSERT_NO_FATAL_FAILURE(Initialize());
434 Decode();
435 EXPECT_EQ(DecodeStatus::OK, last_decode_status());
436 }
437
438 TEST_P(AudioDecoderTest, Reset) {
439 SKIP_TEST_IF_NO_MEDIA_CODEC();
440 ASSERT_NO_FATAL_FAILURE(Initialize());
441 Reset();
442 }
443
444 TEST_P(AudioDecoderTest, NoTimestamp) {
445 SKIP_TEST_IF_NO_MEDIA_CODEC();
446 ASSERT_NO_FATAL_FAILURE(Initialize());
447 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0));
448 buffer->set_timestamp(kNoTimestamp);
449 DecodeBuffer(buffer);
450 EXPECT_EQ(DecodeStatus::DECODE_ERROR, last_decode_status());
451 }
452
453 const DecodedBufferExpectations kBearOpusExpectations[] = { 409 const DecodedBufferExpectations kBearOpusExpectations[] = {
454 {500, 3500, "-0.26,0.87,1.36,0.84,-0.30,-1.22,"}, 410 {500, 3500, "-0.26,0.87,1.36,0.84,-0.30,-1.22,"},
455 {4000, 10000, "0.09,0.23,0.21,0.03,-0.17,-0.24,"}, 411 {4000, 10000, "0.09,0.23,0.21,0.03,-0.17,-0.24,"},
456 {14000, 10000, "0.10,0.24,0.23,0.04,-0.14,-0.23,"}, 412 {14000, 10000, "0.10,0.24,0.23,0.04,-0.14,-0.23,"},
457 }; 413 };
458 414
415 // Test params to test decoder reinitialization. Choose opus because it is
416 // supported on all platforms we test on.
417 const TestParams kReinitializeTestParams = {
418 kCodecOpus, "bear-opus.ogg", kBearOpusExpectations,
419 24, 48000, CHANNEL_LAYOUT_STEREO};
420
459 #if defined(OS_ANDROID) 421 #if defined(OS_ANDROID)
460 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 422 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
461 const DecodedBufferExpectations kSfxAdtsMcExpectations[] = { 423 const DecodedBufferExpectations kSfxAdtsMcExpectations[] = {
462 {0, 23219, "-1.80,-1.49,-0.23,1.11,1.54,-0.11,"}, 424 {0, 23219, "-1.80,-1.49,-0.23,1.11,1.54,-0.11,"},
463 {23219, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"}, 425 {23219, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"},
464 {46439, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"}, 426 {46439, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"},
465 }; 427 };
466 428
467 const DecodedBufferExpectations kHeAacMcExpectations[] = { 429 const DecodedBufferExpectations kHeAacMcExpectations[] = {
468 {0, 42666, "-1.76,-0.12,1.72,1.45,0.10,-1.32,"}, 430 {0, 42666, "-1.76,-0.12,1.72,1.45,0.10,-1.32,"},
469 {42666, 42666, "-1.78,-0.13,1.70,1.44,0.09,-1.32,"}, 431 {42666, 42666, "-1.78,-0.13,1.70,1.44,0.09,-1.32,"},
470 {85333, 42666, "-1.78,-0.13,1.70,1.44,0.08,-1.33,"}, 432 {85333, 42666, "-1.78,-0.13,1.70,1.44,0.08,-1.33,"},
471 }; 433 };
472 #endif 434 #endif // defined(USE_PROPRIETARY_CODECS)
473 435
474 const DecoderTestData kMediaCodecTests[] = { 436 const TestParams kMediaCodecTestParams[] = {
475 {MEDIA_CODEC, kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000, 437 {kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000,
476 CHANNEL_LAYOUT_STEREO}, 438 CHANNEL_LAYOUT_STEREO},
477 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 439 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
478 {MEDIA_CODEC, kCodecAAC, "sfx.adts", kSfxAdtsMcExpectations, 0, 44100, 440 {kCodecAAC, "sfx.adts", kSfxAdtsMcExpectations, 0, 44100,
479 CHANNEL_LAYOUT_MONO}, 441 CHANNEL_LAYOUT_MONO},
480 {MEDIA_CODEC, kCodecAAC, "bear-audio-implicit-he-aac-v2.aac", 442 {kCodecAAC, "bear-audio-implicit-he-aac-v2.aac", kHeAacMcExpectations, 0,
481 kHeAacMcExpectations, 0, 24000, CHANNEL_LAYOUT_MONO}, 443 24000, CHANNEL_LAYOUT_MONO},
482 #endif 444 #endif // defined(USE_PROPRIETARY_CODECS)
483 }; 445 };
484 446
485 INSTANTIATE_TEST_CASE_P(MediaCodec,
486 AudioDecoderTest,
487 testing::ValuesIn(kMediaCodecTests));
488 #endif // defined(OS_ANDROID) 447 #endif // defined(OS_ANDROID)
489 448
490 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 449 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
491 const DecodedBufferExpectations kSfxMp3Expectations[] = { 450 const DecodedBufferExpectations kSfxMp3Expectations[] = {
492 {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"}, 451 {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"},
493 {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"}, 452 {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"},
494 {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"}, 453 {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"},
495 }; 454 };
496 455
497 const DecodedBufferExpectations kSfxAdtsExpectations[] = { 456 const DecodedBufferExpectations kSfxAdtsExpectations[] = {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 {33500, 20000, "-3.44,-3.34,-3.57,-4.11,-4.74,-5.13,"}, 497 {33500, 20000, "-3.44,-3.34,-3.57,-4.11,-4.74,-5.13,"},
539 }; 498 };
540 #else 499 #else
541 const DecodedBufferExpectations kSfxOpusExpectations[] = { 500 const DecodedBufferExpectations kSfxOpusExpectations[] = {
542 {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"}, 501 {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"},
543 {13500, 20000, "5.48,5.93,6.04,5.83,5.54,5.45,"}, 502 {13500, 20000, "5.48,5.93,6.04,5.83,5.54,5.45,"},
544 {33500, 20000, "-3.45,-3.35,-3.57,-4.12,-4.74,-5.14,"}, 503 {33500, 20000, "-3.45,-3.35,-3.57,-4.12,-4.74,-5.14,"},
545 }; 504 };
546 #endif 505 #endif
547 506
548 const DecoderTestData kFFmpegTests[] = { 507 const TestParams kFFmpegTestParams[] = {
549 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 508 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
550 {FFMPEG, kCodecMP3, "sfx.mp3", kSfxMp3Expectations, 0, 44100, 509 {kCodecMP3, "sfx.mp3", kSfxMp3Expectations, 0, 44100, CHANNEL_LAYOUT_MONO},
551 CHANNEL_LAYOUT_MONO}, 510 {kCodecAAC, "sfx.adts", kSfxAdtsExpectations, 0, 44100,
552 {FFMPEG, kCodecAAC, "sfx.adts", kSfxAdtsExpectations, 0, 44100,
553 CHANNEL_LAYOUT_MONO}, 511 CHANNEL_LAYOUT_MONO},
554 #endif 512 #endif
555 {FFMPEG, kCodecFLAC, "sfx.flac", kSfxFlacExpectations, 0, 44100, 513 {kCodecFLAC, "sfx.flac", kSfxFlacExpectations, 0, 44100,
556 CHANNEL_LAYOUT_MONO}, 514 CHANNEL_LAYOUT_MONO},
557 {FFMPEG, kCodecPCM, "sfx_f32le.wav", kSfxWaveExpectations, 0, 44100, 515 {kCodecPCM, "sfx_f32le.wav", kSfxWaveExpectations, 0, 44100,
558 CHANNEL_LAYOUT_MONO}, 516 CHANNEL_LAYOUT_MONO},
559 {FFMPEG, kCodecPCM, "4ch.wav", kFourChannelWaveExpectations, 0, 44100, 517 {kCodecPCM, "4ch.wav", kFourChannelWaveExpectations, 0, 44100,
560 CHANNEL_LAYOUT_QUAD}, 518 CHANNEL_LAYOUT_QUAD},
561 {FFMPEG, kCodecVorbis, "sfx.ogg", kSfxOggExpectations, 0, 44100, 519 {kCodecVorbis, "sfx.ogg", kSfxOggExpectations, 0, 44100,
562 CHANNEL_LAYOUT_MONO}, 520 CHANNEL_LAYOUT_MONO},
563 // Note: bear.ogv is incorrectly muxed such that valid samples are given 521 // Note: bear.ogv is incorrectly muxed such that valid samples are given
564 // negative timestamps, this marks them for discard per the ogg vorbis spec. 522 // negative timestamps, this marks them for discard per the ogg vorbis spec.
565 {FFMPEG, kCodecVorbis, "bear.ogv", kBearOgvExpectations, -704, 44100, 523 {kCodecVorbis, "bear.ogv", kBearOgvExpectations, -704, 44100,
566 CHANNEL_LAYOUT_STEREO}, 524 CHANNEL_LAYOUT_STEREO},
567 {FFMPEG, kCodecOpus, "sfx-opus.ogg", kSfxOpusExpectations, -312, 48000, 525 {kCodecOpus, "sfx-opus.ogg", kSfxOpusExpectations, -312, 48000,
568 CHANNEL_LAYOUT_MONO}, 526 CHANNEL_LAYOUT_MONO},
569 {FFMPEG, kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000, 527 {kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000,
570 CHANNEL_LAYOUT_STEREO}, 528 CHANNEL_LAYOUT_STEREO},
571 }; 529 };
572 530
531 TEST_P(AudioDecoderTest, Initialize) {
532 SKIP_TEST_IF_NOT_SUPPORTED();
533 ASSERT_NO_FATAL_FAILURE(Initialize());
534 }
535
536 TEST_P(AudioDecoderTest, Reinitialize_AfterInitialize) {
537 SKIP_TEST_IF_NOT_SUPPORTED();
538 ASSERT_NO_FATAL_FAILURE(Initialize());
539
540 // Use a different TestParams to reinitialize the decoder.
541 set_params(kReinitializeTestParams);
542
543 SKIP_TEST_IF_NOT_SUPPORTED();
544 ASSERT_NO_FATAL_FAILURE(Initialize());
545 Decode();
546 }
547
548 TEST_P(AudioDecoderTest, Reinitialize_AfterDecode) {
549 SKIP_TEST_IF_NOT_SUPPORTED();
550 ASSERT_NO_FATAL_FAILURE(Initialize());
551 Decode();
552
553 // Use a different TestParams to reinitialize the decoder.
554 set_params(kReinitializeTestParams);
555
556 SKIP_TEST_IF_NOT_SUPPORTED();
557 ASSERT_NO_FATAL_FAILURE(Initialize());
558 Decode();
559 }
560
561 TEST_P(AudioDecoderTest, Reinitialize_AfterReset) {
562 SKIP_TEST_IF_NOT_SUPPORTED();
563 ASSERT_NO_FATAL_FAILURE(Initialize());
564 Decode();
565 Reset();
566
567 // Use a different TestParams to reinitialize the decoder.
568 set_params(kReinitializeTestParams);
569
570 SKIP_TEST_IF_NOT_SUPPORTED();
571 ASSERT_NO_FATAL_FAILURE(Initialize());
572 Decode();
573 }
574
575 // Verifies decode audio as well as the Decode() -> Reset() sequence.
576 TEST_P(AudioDecoderTest, ProduceAudioSamples) {
577 SKIP_TEST_IF_NOT_SUPPORTED();
578 ASSERT_NO_FATAL_FAILURE(Initialize());
579
580 // Run the test multiple times with a seek back to the beginning in between.
581 std::vector<std::string> decoded_audio_md5_hashes;
582 for (int i = 0; i < 2; ++i) {
583 // Run decoder until we get at least |kDecodeRuns| output buffers.
584 // Keeping Decode() in a loop seems to be the simplest way to guarantee that
585 // the predefined number of output buffers are produced without draining
586 // (i.e. decoding EOS).
587 do {
588 Decode();
589 ASSERT_EQ(last_decode_status(), DecodeStatus::OK);
590 } while (decoded_audio_size() < kDecodeRuns);
591
592 // With MediaCodecAudioDecoder the output buffers might appear after
593 // some delay. Since we keep decoding in a loop, the number of output
594 // buffers when they eventually appear might exceed |kDecodeRuns|.
595 ASSERT_LE(kDecodeRuns, decoded_audio_size());
596
597 // On the first pass record the exact MD5 hash for each decoded buffer.
598 if (i == 0) {
599 for (size_t j = 0; j < kDecodeRuns; ++j)
600 decoded_audio_md5_hashes.push_back(GetDecodedAudioMD5(j));
601 }
602
603 // On the first pass verify the basic audio hash and sample info. On the
604 // second, verify the exact MD5 sum for each packet. It shouldn't change.
605 for (size_t j = 0; j < kDecodeRuns; ++j) {
606 SCOPED_TRACE(base::StringPrintf("i = %d, j = %" PRIuS, i, j));
607 ExpectDecodedAudio(j, i == 0 ? "" : decoded_audio_md5_hashes[j]);
608 }
609
610 SendEndOfStream();
611
612 // Seek back to the beginning. Calls Reset() on the decoder.
613 Seek(start_timestamp());
614 }
615 }
616
617 TEST_P(AudioDecoderTest, Decode) {
618 SKIP_TEST_IF_NOT_SUPPORTED();
619 ASSERT_NO_FATAL_FAILURE(Initialize());
620 Decode();
621 EXPECT_EQ(DecodeStatus::OK, last_decode_status());
622 }
623
624 TEST_P(AudioDecoderTest, Reset) {
625 SKIP_TEST_IF_NOT_SUPPORTED();
626 ASSERT_NO_FATAL_FAILURE(Initialize());
627 Reset();
628 }
629
630 TEST_P(AudioDecoderTest, NoTimestamp) {
631 SKIP_TEST_IF_NOT_SUPPORTED();
632 ASSERT_NO_FATAL_FAILURE(Initialize());
633 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0));
634 buffer->set_timestamp(kNoTimestamp);
635 DecodeBuffer(buffer);
636 EXPECT_EQ(DecodeStatus::DECODE_ERROR, last_decode_status());
637 }
638
573 INSTANTIATE_TEST_CASE_P(FFmpeg, 639 INSTANTIATE_TEST_CASE_P(FFmpeg,
574 AudioDecoderTest, 640 AudioDecoderTest,
575 testing::ValuesIn(kFFmpegTests)); 641 Combine(Values(FFMPEG), ValuesIn(kFFmpegTestParams)));
642
643 #if defined(OS_ANDROID)
644 INSTANTIATE_TEST_CASE_P(MediaCodec,
645 AudioDecoderTest,
646 Combine(Values(MEDIA_CODEC),
647 ValuesIn(kMediaCodecTestParams)));
648 #endif // defined(OS_ANDROID)
576 649
577 } // namespace media 650 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/android/media_codec_audio_decoder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698