| 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> | 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |