1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/logging.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "build/build_config.h"
9 #include "media/base/audio_bus.h"
10 #include "media/base/audio_hash.h"
11 #include "media/base/decoder_buffer.h"
12 #include "media/base/test_data_util.h"
13 #include "media/ffmpeg/ffmpeg_common.h"
14 #include "media/filters/audio_file_reader.h"
15 #include "media/filters/in_memory_url_protocol.h"
16 #include "testing/gtest/include/gtest/gtest.h"
20 class AudioFileReaderTest
: public testing::Test
{
22 AudioFileReaderTest() : packet_verification_disabled_(false) {}
23 virtual ~AudioFileReaderTest() {}
25 void Initialize(const char* filename
) {
26 data_
= ReadTestDataFile(filename
);
28 new InMemoryUrlProtocol(data_
->data(), data_
->data_size(), false));
29 reader_
.reset(new AudioFileReader(protocol_
.get()));
32 // Reads and the entire file provided to Initialize().
33 void ReadAndVerify(const char* expected_audio_hash
, int expected_frames
) {
34 scoped_ptr
<AudioBus
> decoded_audio_data
=
35 AudioBus::Create(reader_
->channels(), reader_
->GetNumberOfFrames());
36 int actual_frames
= reader_
->Read(decoded_audio_data
.get());
37 ASSERT_LE(actual_frames
, decoded_audio_data
->frames());
38 ASSERT_EQ(expected_frames
, actual_frames
);
41 audio_hash
.Update(decoded_audio_data
.get(), actual_frames
);
42 EXPECT_EQ(expected_audio_hash
, audio_hash
.ToString());
45 // Verify packets are consistent across demuxer runs. Reads the first few
46 // packets and then seeks back to the start timestamp and verifies that the
47 // hashes match on the packets just read.
48 void VerifyPackets() {
50 const int kTestPasses
= 2;
53 base::TimeDelta start_timestamp
;
54 std::vector
<std::string
> packet_md5_hashes_
;
55 for (int i
= 0; i
< kTestPasses
; ++i
) {
56 for (int j
= 0; j
< kReads
; ++j
) {
57 ASSERT_TRUE(reader_
->ReadPacketForTesting(&packet
));
59 // Remove metadata from the packet data section before hashing.
60 av_packet_split_side_data(&packet
);
62 // On the first pass save the MD5 hash of each packet, on subsequent
63 // passes ensure it matches.
64 const std::string md5_hash
= base::MD5String(base::StringPiece(
65 reinterpret_cast<char*>(packet
.data
), packet
.size
));
67 packet_md5_hashes_
.push_back(md5_hash
);
69 start_timestamp
= ConvertFromTimeBase(
70 reader_
->codec_context_for_testing()->time_base
, packet
.pts
);
73 EXPECT_EQ(packet_md5_hashes_
[j
], md5_hash
) << "j = " << j
;
76 av_free_packet(&packet
);
78 ASSERT_TRUE(reader_
->SeekForTesting(start_timestamp
));
82 void RunTest(const char* fn
,
86 base::TimeDelta duration
,
90 ASSERT_TRUE(reader_
->Open());
91 EXPECT_EQ(channels
, reader_
->channels());
92 EXPECT_EQ(sample_rate
, reader_
->sample_rate());
93 EXPECT_EQ(duration
.InMicroseconds(),
94 reader_
->GetDuration().InMicroseconds());
95 EXPECT_EQ(frames
, reader_
->GetNumberOfFrames());
96 if (!packet_verification_disabled_
)
97 ASSERT_NO_FATAL_FAILURE(VerifyPackets());
98 ReadAndVerify(hash
, trimmed_frames
);
101 void RunTestFailingDemux(const char* fn
) {
103 EXPECT_FALSE(reader_
->Open());
106 void RunTestFailingDecode(const char* fn
) {
108 EXPECT_TRUE(reader_
->Open());
109 scoped_ptr
<AudioBus
> decoded_audio_data
=
110 AudioBus::Create(reader_
->channels(), reader_
->GetNumberOfFrames());
111 EXPECT_EQ(reader_
->Read(decoded_audio_data
.get()), 0);
114 void disable_packet_verification() {
115 packet_verification_disabled_
= true;
119 scoped_refptr
<DecoderBuffer
> data_
;
120 scoped_ptr
<InMemoryUrlProtocol
> protocol_
;
121 scoped_ptr
<AudioFileReader
> reader_
;
122 bool packet_verification_disabled_
;
124 DISALLOW_COPY_AND_ASSIGN(AudioFileReaderTest
);
127 TEST_F(AudioFileReaderTest
, WithoutOpen
) {
128 Initialize("bear.ogv");
131 TEST_F(AudioFileReaderTest
, InvalidFile
) {
132 RunTestFailingDemux("ten_byte_file");
135 TEST_F(AudioFileReaderTest
, WithVideo
) {
137 "-2.49,-0.75,0.38,1.60,0.70,-1.22,",
140 base::TimeDelta::FromMicroseconds(1011520),
145 TEST_F(AudioFileReaderTest
, Vorbis
) {
147 "4.36,4.81,4.84,4.45,4.61,4.63,",
150 base::TimeDelta::FromMicroseconds(350001),
155 TEST_F(AudioFileReaderTest
, WaveU8
) {
156 RunTest("sfx_u8.wav",
157 "-1.23,-1.57,-1.14,-0.91,-0.87,-0.07,",
160 base::TimeDelta::FromMicroseconds(288414),
165 TEST_F(AudioFileReaderTest
, WaveS16LE
) {
166 RunTest("sfx_s16le.wav",
167 "3.05,2.87,3.00,3.32,3.58,4.08,",
170 base::TimeDelta::FromMicroseconds(288414),
175 TEST_F(AudioFileReaderTest
, WaveS24LE
) {
176 RunTest("sfx_s24le.wav",
177 "3.03,2.86,2.99,3.31,3.57,4.06,",
180 base::TimeDelta::FromMicroseconds(288414),
185 TEST_F(AudioFileReaderTest
, WaveF32LE
) {
186 RunTest("sfx_f32le.wav",
187 "3.03,2.86,2.99,3.31,3.57,4.06,",
190 base::TimeDelta::FromMicroseconds(288414),
195 #if defined(USE_PROPRIETARY_CODECS)
196 TEST_F(AudioFileReaderTest
, MP3
) {
198 "3.05,2.87,3.00,3.32,3.58,4.08,",
201 base::TimeDelta::FromMicroseconds(313470),
206 TEST_F(AudioFileReaderTest
, CorruptMP3
) {
207 // Disable packet verification since the file is corrupt and FFmpeg does not
208 // make any guarantees on packet consistency in this case.
209 disable_packet_verification();
210 RunTest("corrupt.mp3",
211 "-4.95,-2.95,-0.44,1.16,0.31,-2.21,",
214 base::TimeDelta::FromMicroseconds(1018826),
219 TEST_F(AudioFileReaderTest
, AAC
) {
221 "1.81,1.66,2.32,3.27,4.46,3.36,",
224 base::TimeDelta::FromMicroseconds(312001),
229 TEST_F(AudioFileReaderTest
, MidStreamConfigChangesFail
) {
230 RunTestFailingDecode("midstream_config_change.mp3");
234 TEST_F(AudioFileReaderTest
, VorbisInvalidChannelLayout
) {
235 RunTestFailingDemux("9ch.ogg");
238 TEST_F(AudioFileReaderTest
, WaveValidFourChannelLayout
) {
240 "131.71,38.02,130.31,44.89,135.98,42.52,",
243 base::TimeDelta::FromMicroseconds(100001),