Removed unused VideoCaptureCapability parameters.
[chromium-blink-merge.git] / media / tools / demuxer_bench / demuxer_bench.cc
blobab8b313c435c1213eab9a676504c175bc4fc830b
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 // demuxer_bench is a standalone benchmarking tool for FFmpegDemuxer. It
6 // simulates the reading requirements for playback by reading from the stream
7 // that has the earliest timestamp.
9 #include <iostream>
11 #include "base/at_exit.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "media/base/media.h"
18 #include "media/base/media_log.h"
19 #include "media/filters/ffmpeg_demuxer.h"
20 #include "media/filters/file_data_source.h"
22 namespace switches {
23 const char kEnableBitstreamConverter[] = "enable-bitstream-converter";
24 } // namespace switches
26 class DemuxerHostImpl : public media::DemuxerHost {
27 public:
28 DemuxerHostImpl() {}
29 virtual ~DemuxerHostImpl() {}
31 // DataSourceHost implementation.
32 virtual void SetTotalBytes(int64 total_bytes) OVERRIDE {}
33 virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE {}
34 virtual void AddBufferedTimeRange(base::TimeDelta start,
35 base::TimeDelta end) OVERRIDE {}
37 // DemuxerHost implementation.
38 virtual void SetDuration(base::TimeDelta duration) OVERRIDE {}
39 virtual void OnDemuxerError(media::PipelineStatus error) OVERRIDE {}
41 private:
42 DISALLOW_COPY_AND_ASSIGN(DemuxerHostImpl);
45 void QuitLoopWithStatus(base::MessageLoop* message_loop,
46 media::PipelineStatus status) {
47 CHECK_EQ(status, media::PIPELINE_OK);
48 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
51 static void NeedKey(const std::string& type,
52 const std::vector<uint8>& init_data) {
53 LOG(INFO) << "File is encrypted.";
56 typedef std::vector<media::DemuxerStream* > Streams;
58 // Simulates playback reading requirements by reading from each stream
59 // present in |demuxer| in as-close-to-monotonically-increasing timestamp order.
60 class StreamReader {
61 public:
62 StreamReader(media::Demuxer* demuxer, bool enable_bitstream_converter);
63 ~StreamReader();
65 // Performs a single step read.
66 void Read();
68 // Returns true when all streams have reached end of stream.
69 bool IsDone();
71 int number_of_streams() { return streams_.size(); }
72 const Streams& streams() { return streams_; }
73 const std::vector<int>& counts() { return counts_; }
75 private:
76 void OnReadDone(base::MessageLoop* message_loop,
77 bool* end_of_stream,
78 base::TimeDelta* timestamp,
79 media::DemuxerStream::Status status,
80 const scoped_refptr<media::DecoderBuffer>& buffer);
81 int GetNextStreamIndexToRead();
83 Streams streams_;
84 std::vector<bool> end_of_stream_;
85 std::vector<base::TimeDelta> last_read_timestamp_;
86 std::vector<int> counts_;
88 DISALLOW_COPY_AND_ASSIGN(StreamReader);
91 StreamReader::StreamReader(media::Demuxer* demuxer,
92 bool enable_bitstream_converter) {
93 media::DemuxerStream* stream =
94 demuxer->GetStream(media::DemuxerStream::AUDIO);
95 if (stream) {
96 streams_.push_back(stream);
97 end_of_stream_.push_back(false);
98 last_read_timestamp_.push_back(media::kNoTimestamp());
99 counts_.push_back(0);
102 stream = demuxer->GetStream(media::DemuxerStream::VIDEO);
103 if (stream) {
104 streams_.push_back(stream);
105 end_of_stream_.push_back(false);
106 last_read_timestamp_.push_back(media::kNoTimestamp());
107 counts_.push_back(0);
109 if (enable_bitstream_converter)
110 stream->EnableBitstreamConverter();
114 StreamReader::~StreamReader() {}
116 void StreamReader::Read() {
117 int index = GetNextStreamIndexToRead();
118 bool end_of_stream = false;
119 base::TimeDelta timestamp;
121 streams_[index]->Read(base::Bind(
122 &StreamReader::OnReadDone, base::Unretained(this),
123 base::MessageLoop::current(), &end_of_stream, &timestamp));
124 base::MessageLoop::current()->Run();
126 CHECK(end_of_stream || timestamp != media::kNoTimestamp());
127 end_of_stream_[index] = end_of_stream;
128 last_read_timestamp_[index] = timestamp;
129 counts_[index]++;
132 bool StreamReader::IsDone() {
133 for (size_t i = 0; i < end_of_stream_.size(); ++i) {
134 if (!end_of_stream_[i])
135 return false;
137 return true;
140 void StreamReader::OnReadDone(
141 base::MessageLoop* message_loop,
142 bool* end_of_stream,
143 base::TimeDelta* timestamp,
144 media::DemuxerStream::Status status,
145 const scoped_refptr<media::DecoderBuffer>& buffer) {
146 CHECK_EQ(status, media::DemuxerStream::kOk);
147 CHECK(buffer.get());
148 *end_of_stream = buffer->end_of_stream();
149 *timestamp = *end_of_stream ? media::kNoTimestamp() : buffer->timestamp();
150 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
153 int StreamReader::GetNextStreamIndexToRead() {
154 int index = -1;
155 for (int i = 0; i < number_of_streams(); ++i) {
156 // Ignore streams at EOS.
157 if (end_of_stream_[i])
158 continue;
160 // Use a stream if it hasn't been read from yet.
161 if (last_read_timestamp_[i] == media::kNoTimestamp())
162 return i;
164 if (index < 0 ||
165 last_read_timestamp_[i] < last_read_timestamp_[index]) {
166 index = i;
169 CHECK_GE(index, 0) << "Couldn't find a stream to read";
170 return index;
173 int main(int argc, char** argv) {
174 base::AtExitManager at_exit;
175 media::InitializeMediaLibraryForTesting();
177 CommandLine::Init(argc, argv);
178 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
180 if (cmd_line->GetArgs().empty()) {
181 std::cerr << "Usage: " << argv[0] << " [file]\n\n"
182 << "Options:\n"
183 << " --" << switches::kEnableBitstreamConverter
184 << " Enables H.264 Annex B bitstream conversion"
185 << std::endl;
186 return 1;
189 base::MessageLoop message_loop;
190 DemuxerHostImpl demuxer_host;
191 base::FilePath file_path(cmd_line->GetArgs()[0]);
193 // Setup.
194 media::FileDataSource data_source;
195 CHECK(data_source.Initialize(file_path));
197 media::Demuxer::NeedKeyCB need_key_cb = base::Bind(&NeedKey);
198 media::FFmpegDemuxer demuxer(message_loop.message_loop_proxy(),
199 &data_source,
200 need_key_cb,
201 new media::MediaLog());
203 demuxer.Initialize(&demuxer_host, base::Bind(
204 &QuitLoopWithStatus, &message_loop));
205 message_loop.Run();
207 StreamReader stream_reader(
208 &demuxer, cmd_line->HasSwitch(switches::kEnableBitstreamConverter));
210 // Benchmark.
211 base::TimeTicks start = base::TimeTicks::HighResNow();
212 while (!stream_reader.IsDone()) {
213 stream_reader.Read();
215 base::TimeTicks end = base::TimeTicks::HighResNow();
217 // Results.
218 std::cout << "Time: " << (end - start).InMillisecondsF() << " ms\n";
219 for (int i = 0; i < stream_reader.number_of_streams(); ++i) {
220 media::DemuxerStream* stream = stream_reader.streams()[i];
221 std::cout << "Stream #" << i << ": ";
223 if (stream->type() == media::DemuxerStream::AUDIO) {
224 std::cout << "audio";
225 } else if (stream->type() == media::DemuxerStream::VIDEO) {
226 std::cout << "video";
227 } else {
228 std::cout << "unknown";
231 std::cout << ", " << stream_reader.counts()[i] << " packets" << std::endl;
234 // Teardown.
235 demuxer.Stop(base::Bind(
236 &QuitLoopWithStatus, &message_loop, media::PIPELINE_OK));
237 message_loop.Run();
239 return 0;