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#ifndef MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
6#define MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
7
8#include "base/md5.h"
9#include "base/message_loop/message_loop.h"
10#include "media/audio/clockless_audio_sink.h"
11#include "media/audio/null_audio_sink.h"
12#include "media/base/demuxer.h"
13#include "media/base/filter_collection.h"
14#include "media/base/media_keys.h"
15#include "media/base/pipeline.h"
16#include "media/base/video_frame.h"
17#include "media/filters/video_renderer_impl.h"
18#include "testing/gmock/include/gmock/gmock.h"
19
20namespace base {
21class FilePath;
22}
23
24namespace media {
25
26class Decryptor;
27
28// Empty MD5 hash string.  Used to verify empty video tracks.
29extern const char kNullVideoHash[];
30
31// Empty hash string.  Used to verify empty audio tracks.
32extern const char kNullAudioHash[];
33
34// Dummy tick clock which advances extremely quickly (1 minute every time
35// NowTicks() is called).
36class DummyTickClock : public base::TickClock {
37 public:
38  DummyTickClock() : now_() {}
39  virtual ~DummyTickClock() {}
40  virtual base::TimeTicks NowTicks() OVERRIDE;
41 private:
42  base::TimeTicks now_;
43};
44
45// Integration tests for Pipeline. Real demuxers, real decoders, and
46// base renderer implementations are used to verify pipeline functionality. The
47// renderers used in these tests rely heavily on the AudioRendererBase &
48// VideoRendererImpl implementations which contain a majority of the code used
49// in the real AudioRendererImpl & SkCanvasVideoRenderer implementations used in
50// the browser. The renderers in this test don't actually write data to a
51// display or audio device. Both of these devices are simulated since they have
52// little effect on verifying pipeline behavior and allow tests to run faster
53// than real-time.
54class PipelineIntegrationTestBase {
55 public:
56  PipelineIntegrationTestBase();
57  virtual ~PipelineIntegrationTestBase();
58
59  bool WaitUntilOnEnded();
60  PipelineStatus WaitUntilEndedOrError();
61  bool Start(const base::FilePath& file_path, PipelineStatus expected_status);
62  // Enable playback with audio and video hashing enabled, or clockless
63  // playback (audio only). Frame dropping and audio underflow will be disabled
64  // if hashing enabled to ensure consistent hashes.
65  enum kTestType { kHashed, kClockless };
66  bool Start(const base::FilePath& file_path,
67             PipelineStatus expected_status,
68             kTestType test_type);
69  // Initialize the pipeline and ignore any status updates.  Useful for testing
70  // invalid audio/video clips which don't have deterministic results.
71  bool Start(const base::FilePath& file_path);
72  bool Start(const base::FilePath& file_path, Decryptor* decryptor);
73
74  void Play();
75  void Pause();
76  bool Seek(base::TimeDelta seek_time);
77  void Stop();
78  bool WaitUntilCurrentTimeIsAfter(const base::TimeDelta& wait_time);
79  scoped_ptr<FilterCollection> CreateFilterCollection(
80      const base::FilePath& file_path, Decryptor* decryptor);
81
82  // Returns the MD5 hash of all video frames seen.  Should only be called once
83  // after playback completes.  First time hashes should be generated with
84  // --video-threads=1 to ensure correctness.  Pipeline must have been started
85  // with hashing enabled.
86  std::string GetVideoHash();
87
88  // Returns the hash of all audio frames seen.  Should only be called once
89  // after playback completes.  Pipeline must have been started with hashing
90  // enabled.
91  std::string GetAudioHash();
92
93  // Returns the time taken to render the complete audio file.
94  // Pipeline must have been started with clockless playback enabled.
95  base::TimeDelta GetAudioTime();
96
97 protected:
98  base::MessageLoop message_loop_;
99  base::MD5Context md5_context_;
100  bool hashing_enabled_;
101  bool clockless_playback_;
102  scoped_ptr<Demuxer> demuxer_;
103  scoped_ptr<DataSource> data_source_;
104  scoped_ptr<Pipeline> pipeline_;
105  scoped_refptr<NullAudioSink> audio_sink_;
106  scoped_refptr<ClocklessAudioSink> clockless_audio_sink_;
107  bool ended_;
108  PipelineStatus pipeline_status_;
109  Demuxer::NeedKeyCB need_key_cb_;
110  VideoFrame::Format last_video_frame_format_;
111  DummyTickClock dummy_clock_;
112
113  void OnStatusCallbackChecked(PipelineStatus expected_status,
114                               PipelineStatus status);
115  void OnStatusCallback(PipelineStatus status);
116  PipelineStatusCB QuitOnStatusCB(PipelineStatus expected_status);
117  void DemuxerNeedKeyCB(const std::string& type,
118                        const std::vector<uint8>& init_data);
119  void set_need_key_cb(const Demuxer::NeedKeyCB& need_key_cb) {
120    need_key_cb_ = need_key_cb;
121  }
122
123  void OnEnded();
124  void OnError(PipelineStatus status);
125  void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time);
126  scoped_ptr<FilterCollection> CreateFilterCollection(
127      scoped_ptr<Demuxer> demuxer, Decryptor* decryptor);
128
129  void SetDecryptor(Decryptor* decryptor,
130                    const DecryptorReadyCB& decryptor_ready_cb);
131  void OnVideoRendererPaint(const scoped_refptr<VideoFrame>& frame);
132
133  MOCK_METHOD1(OnSetOpaque, void(bool));
134  MOCK_METHOD1(OnBufferingState, void(Pipeline::BufferingState));
135};
136
137}  // namespace media
138
139#endif  // MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
140