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.
4
5#include "base/logging.h"
6#include "base/md5.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"
17
18namespace media {
19
20class AudioFileReaderTest : public testing::Test {
21 public:
22  AudioFileReaderTest() : packet_verification_disabled_(false) {}
23  virtual ~AudioFileReaderTest() {}
24
25  void Initialize(const char* filename) {
26    data_ = ReadTestDataFile(filename);
27    protocol_.reset(
28        new InMemoryUrlProtocol(data_->data(), data_->data_size(), false));
29    reader_.reset(new AudioFileReader(protocol_.get()));
30  }
31
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);
39
40    AudioHash audio_hash;
41    audio_hash.Update(decoded_audio_data.get(), actual_frames);
42    EXPECT_EQ(expected_audio_hash, audio_hash.ToString());
43  }
44
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() {
49    const int kReads = 3;
50    const int kTestPasses = 2;
51
52    AVPacket packet;
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));
58
59        // Remove metadata from the packet data section before hashing.
60        av_packet_split_side_data(&packet);
61
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));
66        if (i == 0) {
67          packet_md5_hashes_.push_back(md5_hash);
68          if (j == 0) {
69            start_timestamp = ConvertFromTimeBase(
70                reader_->codec_context_for_testing()->time_base, packet.pts);
71          }
72        } else {
73          EXPECT_EQ(packet_md5_hashes_[j], md5_hash) << "j = " << j;
74        }
75
76        av_free_packet(&packet);
77      }
78      ASSERT_TRUE(reader_->SeekForTesting(start_timestamp));
79    }
80  }
81
82  void RunTest(const char* fn,
83               const char* hash,
84               int channels,
85               int sample_rate,
86               base::TimeDelta duration,
87               int frames,
88               int trimmed_frames) {
89    Initialize(fn);
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);
99  }
100
101  void RunTestFailingDemux(const char* fn) {
102    Initialize(fn);
103    EXPECT_FALSE(reader_->Open());
104  }
105
106  void RunTestFailingDecode(const char* fn) {
107    Initialize(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);
112  }
113
114  void disable_packet_verification() {
115    packet_verification_disabled_ = true;
116  }
117
118 protected:
119  scoped_refptr<DecoderBuffer> data_;
120  scoped_ptr<InMemoryUrlProtocol> protocol_;
121  scoped_ptr<AudioFileReader> reader_;
122  bool packet_verification_disabled_;
123
124  DISALLOW_COPY_AND_ASSIGN(AudioFileReaderTest);
125};
126
127TEST_F(AudioFileReaderTest, WithoutOpen) {
128  Initialize("bear.ogv");
129}
130
131TEST_F(AudioFileReaderTest, InvalidFile) {
132  RunTestFailingDemux("ten_byte_file");
133}
134
135TEST_F(AudioFileReaderTest, WithVideo) {
136  RunTest("bear.ogv",
137          "-2.49,-0.75,0.38,1.60,0.70,-1.22,",
138          2,
139          44100,
140          base::TimeDelta::FromMicroseconds(1011520),
141          44609,
142          44609);
143}
144
145TEST_F(AudioFileReaderTest, Vorbis) {
146  RunTest("sfx.ogg",
147          "4.36,4.81,4.84,4.45,4.61,4.63,",
148          1,
149          44100,
150          base::TimeDelta::FromMicroseconds(350001),
151          15436,
152          15436);
153}
154
155TEST_F(AudioFileReaderTest, WaveU8) {
156  RunTest("sfx_u8.wav",
157          "-1.23,-1.57,-1.14,-0.91,-0.87,-0.07,",
158          1,
159          44100,
160          base::TimeDelta::FromMicroseconds(288414),
161          12720,
162          12719);
163}
164
165TEST_F(AudioFileReaderTest, WaveS16LE) {
166  RunTest("sfx_s16le.wav",
167          "3.05,2.87,3.00,3.32,3.58,4.08,",
168          1,
169          44100,
170          base::TimeDelta::FromMicroseconds(288414),
171          12720,
172          12719);
173}
174
175TEST_F(AudioFileReaderTest, WaveS24LE) {
176  RunTest("sfx_s24le.wav",
177          "3.03,2.86,2.99,3.31,3.57,4.06,",
178          1,
179          44100,
180          base::TimeDelta::FromMicroseconds(288414),
181          12720,
182          12719);
183}
184
185TEST_F(AudioFileReaderTest, WaveF32LE) {
186  RunTest("sfx_f32le.wav",
187          "3.03,2.86,2.99,3.31,3.57,4.06,",
188          1,
189          44100,
190          base::TimeDelta::FromMicroseconds(288414),
191          12720,
192          12719);
193}
194
195#if defined(USE_PROPRIETARY_CODECS)
196TEST_F(AudioFileReaderTest, MP3) {
197  RunTest("sfx.mp3",
198          "5.59,7.11,6.63,6.23,5.58,5.22,",
199          1,
200          44100,
201          base::TimeDelta::FromMicroseconds(313470),
202          13825,
203          10496);
204}
205
206TEST_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,",
212          1,
213          44100,
214          base::TimeDelta::FromMicroseconds(1018826),
215          44931,
216          44928);
217}
218
219TEST_F(AudioFileReaderTest, AAC) {
220  RunTest("sfx.m4a",
221          "1.81,1.66,2.32,3.27,4.46,3.36,",
222          1,
223          44100,
224          base::TimeDelta::FromMicroseconds(312001),
225          13760,
226          13312);
227}
228
229TEST_F(AudioFileReaderTest, MidStreamConfigChangesFail) {
230  RunTestFailingDecode("midstream_config_change.mp3");
231}
232#endif
233
234TEST_F(AudioFileReaderTest, VorbisInvalidChannelLayout) {
235  RunTestFailingDemux("9ch.ogg");
236}
237
238TEST_F(AudioFileReaderTest, WaveValidFourChannelLayout) {
239  RunTest("4ch.wav",
240          "131.71,38.02,130.31,44.89,135.98,42.52,",
241          4,
242          44100,
243          base::TimeDelta::FromMicroseconds(100001),
244          4411,
245          4410);
246}
247
248}  // namespace media
249