Improve back button behavior.
[chromium-blink-merge.git] / media / base / demuxer_perftest.cc
blob4f740de8baf94960f1e4ebedafacd8ff33b8db56
1 // Copyright 2013 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/at_exit.h"
6 #include "base/bind.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/time/time.h"
10 #include "media/base/media.h"
11 #include "media/base/media_log.h"
12 #include "media/base/test_data_util.h"
13 #include "media/base/timestamp_constants.h"
14 #include "media/filters/ffmpeg_demuxer.h"
15 #include "media/filters/file_data_source.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/perf/perf_test.h"
19 namespace media {
21 static const int kBenchmarkIterations = 100;
23 class DemuxerHostImpl : public media::DemuxerHost {
24 public:
25 DemuxerHostImpl() {}
26 ~DemuxerHostImpl() override {}
28 // DemuxerHost implementation.
29 void AddBufferedTimeRange(base::TimeDelta start,
30 base::TimeDelta end) override {}
31 void SetDuration(base::TimeDelta duration) override {}
32 void OnDemuxerError(media::PipelineStatus error) override {}
33 void AddTextStream(media::DemuxerStream* text_stream,
34 const media::TextTrackConfig& config) override {}
35 void RemoveTextStream(media::DemuxerStream* text_stream) override {}
37 private:
38 DISALLOW_COPY_AND_ASSIGN(DemuxerHostImpl);
41 static void QuitLoopWithStatus(base::MessageLoop* message_loop,
42 media::PipelineStatus status) {
43 CHECK_EQ(status, media::PIPELINE_OK);
44 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
47 static void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
48 const std::vector<uint8>& init_data) {
49 VLOG(0) << "File is encrypted.";
52 typedef std::vector<media::DemuxerStream* > Streams;
54 // Simulates playback reading requirements by reading from each stream
55 // present in |demuxer| in as-close-to-monotonically-increasing timestamp order.
56 class StreamReader {
57 public:
58 StreamReader(media::Demuxer* demuxer, bool enable_bitstream_converter);
59 ~StreamReader();
61 // Performs a single step read.
62 void Read();
64 // Returns true when all streams have reached end of stream.
65 bool IsDone();
67 int number_of_streams() { return static_cast<int>(streams_.size()); }
68 const Streams& streams() { return streams_; }
69 const std::vector<int>& counts() { return counts_; }
71 private:
72 void OnReadDone(base::MessageLoop* message_loop,
73 bool* end_of_stream,
74 base::TimeDelta* timestamp,
75 media::DemuxerStream::Status status,
76 const scoped_refptr<media::DecoderBuffer>& buffer);
77 int GetNextStreamIndexToRead();
79 Streams streams_;
80 std::vector<bool> end_of_stream_;
81 std::vector<base::TimeDelta> last_read_timestamp_;
82 std::vector<int> counts_;
84 DISALLOW_COPY_AND_ASSIGN(StreamReader);
87 StreamReader::StreamReader(media::Demuxer* demuxer,
88 bool enable_bitstream_converter) {
89 media::DemuxerStream* stream =
90 demuxer->GetStream(media::DemuxerStream::AUDIO);
91 if (stream) {
92 streams_.push_back(stream);
93 end_of_stream_.push_back(false);
94 last_read_timestamp_.push_back(media::kNoTimestamp());
95 counts_.push_back(0);
98 stream = demuxer->GetStream(media::DemuxerStream::VIDEO);
99 if (stream) {
100 streams_.push_back(stream);
101 end_of_stream_.push_back(false);
102 last_read_timestamp_.push_back(media::kNoTimestamp());
103 counts_.push_back(0);
105 if (enable_bitstream_converter)
106 stream->EnableBitstreamConverter();
110 StreamReader::~StreamReader() {}
112 void StreamReader::Read() {
113 int index = GetNextStreamIndexToRead();
114 bool end_of_stream = false;
115 base::TimeDelta timestamp;
117 streams_[index]->Read(base::Bind(
118 &StreamReader::OnReadDone, base::Unretained(this),
119 base::MessageLoop::current(), &end_of_stream, &timestamp));
120 base::MessageLoop::current()->Run();
122 CHECK(end_of_stream || timestamp != media::kNoTimestamp());
123 end_of_stream_[index] = end_of_stream;
124 last_read_timestamp_[index] = timestamp;
125 counts_[index]++;
128 bool StreamReader::IsDone() {
129 for (size_t i = 0; i < end_of_stream_.size(); ++i) {
130 if (!end_of_stream_[i])
131 return false;
133 return true;
136 void StreamReader::OnReadDone(
137 base::MessageLoop* message_loop,
138 bool* end_of_stream,
139 base::TimeDelta* timestamp,
140 media::DemuxerStream::Status status,
141 const scoped_refptr<media::DecoderBuffer>& buffer) {
142 CHECK_EQ(status, media::DemuxerStream::kOk);
143 CHECK(buffer.get());
144 *end_of_stream = buffer->end_of_stream();
145 *timestamp = *end_of_stream ? media::kNoTimestamp() : buffer->timestamp();
146 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
149 int StreamReader::GetNextStreamIndexToRead() {
150 int index = -1;
151 for (int i = 0; i < number_of_streams(); ++i) {
152 // Ignore streams at EOS.
153 if (end_of_stream_[i])
154 continue;
156 // Use a stream if it hasn't been read from yet.
157 if (last_read_timestamp_[i] == media::kNoTimestamp())
158 return i;
160 if (index < 0 ||
161 last_read_timestamp_[i] < last_read_timestamp_[index]) {
162 index = i;
165 CHECK_GE(index, 0) << "Couldn't find a stream to read";
166 return index;
169 static void RunDemuxerBenchmark(const std::string& filename) {
170 base::FilePath file_path(GetTestDataFilePath(filename));
171 double total_time = 0.0;
172 for (int i = 0; i < kBenchmarkIterations; ++i) {
173 // Setup.
174 base::MessageLoop message_loop;
175 DemuxerHostImpl demuxer_host;
176 FileDataSource data_source;
177 ASSERT_TRUE(data_source.Initialize(file_path));
179 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
180 base::Bind(&OnEncryptedMediaInitData);
181 FFmpegDemuxer demuxer(message_loop.task_runner(), &data_source,
182 encrypted_media_init_data_cb, new MediaLog());
184 demuxer.Initialize(&demuxer_host,
185 base::Bind(&QuitLoopWithStatus, &message_loop),
186 false);
187 message_loop.Run();
188 StreamReader stream_reader(&demuxer, false);
190 // Benchmark.
191 base::TimeTicks start = base::TimeTicks::Now();
192 while (!stream_reader.IsDone()) {
193 stream_reader.Read();
195 base::TimeTicks end = base::TimeTicks::Now();
196 total_time += (end - start).InSecondsF();
197 demuxer.Stop();
198 QuitLoopWithStatus(&message_loop, PIPELINE_OK);
199 message_loop.Run();
202 perf_test::PrintResult("demuxer_bench",
204 filename,
205 kBenchmarkIterations / total_time,
206 "runs/s",
207 true);
210 #if defined(OS_WIN)
211 // http://crbug.com/399002
212 #define MAYBE_Demuxer DISABLED_Demuxer
213 #else
214 #define MAYBE_Demuxer Demuxer
215 #endif
216 TEST(DemuxerPerfTest, MAYBE_Demuxer) {
217 RunDemuxerBenchmark("bear.ogv");
218 RunDemuxerBenchmark("bear-640x360.webm");
219 RunDemuxerBenchmark("sfx_s16le.wav");
220 #if defined(USE_PROPRIETARY_CODECS)
221 RunDemuxerBenchmark("bear-1280x720.mp4");
222 RunDemuxerBenchmark("sfx.mp3");
223 #endif
224 #if defined(OS_CHROMEOS)
225 RunDemuxerBenchmark("bear.flac");
226 #endif
227 #if defined(USE_PROPRIETARY_CODECS) && defined(OS_CHROMEOS)
228 RunDemuxerBenchmark("bear.avi");
229 #endif
232 } // namespace media