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/audio_hardware_config.h"
13#include "media/base/demuxer.h"
14#include "media/base/media_keys.h"
15#include "media/base/pipeline.h"
16#include "media/base/text_track.h"
17#include "media/base/text_track_config.h"
18#include "media/base/video_frame.h"
19#include "media/filters/video_renderer_impl.h"
20#include "testing/gmock/include/gmock/gmock.h"
21
22namespace base {
23class FilePath;
24}
25
26namespace media {
27
28class Decryptor;
29
30// Empty MD5 hash string.  Used to verify empty video tracks.
31extern const char kNullVideoHash[];
32
33// Empty hash string.  Used to verify empty audio tracks.
34extern const char kNullAudioHash[];
35
36// Dummy tick clock which advances extremely quickly (1 minute every time
37// NowTicks() is called).
38class DummyTickClock : public base::TickClock {
39 public:
40  DummyTickClock() : now_() {}
41  virtual ~DummyTickClock() {}
42  virtual base::TimeTicks NowTicks() OVERRIDE;
43 private:
44  base::TimeTicks now_;
45};
46
47// Integration tests for Pipeline. Real demuxers, real decoders, and
48// base renderer implementations are used to verify pipeline functionality. The
49// renderers used in these tests rely heavily on the AudioRendererBase &
50// VideoRendererImpl implementations which contain a majority of the code used
51// in the real AudioRendererImpl & SkCanvasVideoRenderer implementations used in
52// the browser. The renderers in this test don't actually write data to a
53// display or audio device. Both of these devices are simulated since they have
54// little effect on verifying pipeline behavior and allow tests to run faster
55// than real-time.
56class PipelineIntegrationTestBase {
57 public:
58  PipelineIntegrationTestBase();
59  virtual ~PipelineIntegrationTestBase();
60
61  bool WaitUntilOnEnded();
62  PipelineStatus WaitUntilEndedOrError();
63  bool Start(const base::FilePath& file_path, PipelineStatus expected_status);
64  // Enable playback with audio and video hashing enabled, or clockless
65  // playback (audio only). Frame dropping and audio underflow will be disabled
66  // if hashing enabled to ensure consistent hashes.
67  enum kTestType { kHashed, kClockless };
68  bool Start(const base::FilePath& file_path,
69             PipelineStatus expected_status,
70             kTestType test_type);
71  // Initialize the pipeline and ignore any status updates.  Useful for testing
72  // invalid audio/video clips which don't have deterministic results.
73  bool Start(const base::FilePath& file_path);
74  bool Start(const base::FilePath& file_path, Decryptor* decryptor);
75
76  void Play();
77  void Pause();
78  bool Seek(base::TimeDelta seek_time);
79  void Stop();
80  bool WaitUntilCurrentTimeIsAfter(const base::TimeDelta& wait_time);
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  AudioHardwareConfig hardware_config_;
113  PipelineMetadata metadata_;
114
115  void OnStatusCallbackChecked(PipelineStatus expected_status,
116                               PipelineStatus status);
117  void OnStatusCallback(PipelineStatus status);
118  PipelineStatusCB QuitOnStatusCB(PipelineStatus expected_status);
119  void DemuxerNeedKeyCB(const std::string& type,
120                        const std::vector<uint8>& init_data);
121  void set_need_key_cb(const Demuxer::NeedKeyCB& need_key_cb) {
122    need_key_cb_ = need_key_cb;
123  }
124
125  void OnEnded();
126  void OnError(PipelineStatus status);
127  void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time);
128
129  // Creates Demuxer and sets |demuxer_|.
130  void CreateDemuxer(const base::FilePath& file_path);
131
132  // Creates and returns a Renderer.
133  scoped_ptr<Renderer> CreateRenderer(Decryptor* decryptor);
134
135  void SetDecryptor(Decryptor* decryptor,
136                    const DecryptorReadyCB& decryptor_ready_cb);
137  void OnVideoRendererPaint(const scoped_refptr<VideoFrame>& frame);
138
139  MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
140  MOCK_METHOD1(OnBufferingStateChanged, void(BufferingState));
141  MOCK_METHOD1(DecryptorAttached, void(bool));
142  MOCK_METHOD2(OnAddTextTrack,
143               void(const TextTrackConfig& config,
144                    const AddTextTrackDoneCB& done_cb));
145};
146
147}  // namespace media
148
149#endif  // MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
150