forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpipeline_controller.h
200 lines (165 loc) · 7.31 KB
/
pipeline_controller.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FILTERS_PIPELINE_CONTROLLER_H_
#define MEDIA_FILTERS_PIPELINE_CONTROLLER_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "media/base/media_export.h"
#include "media/base/pipeline.h"
#include "media/base/renderer.h"
namespace media {
class Demuxer;
// PipelineController wraps a Pipeline to expose the one-at-a-time operations
// (Seek(), Suspend(), and Resume()) with a simpler API. Internally it tracks
// pending operations and dispatches them when possible. Duplicate requests
// (such as seeking twice to the same time) may be elided.
//
// TODO(sandersd/tguilbert):
// - Expose an operation that replaces the Renderer (via Suspend/Resume).
// - Expose an operation that replaces the Demuxer (via Start/Stop). This will
// also implicitly replace the Renderer.
// - Block invalid calls after an error occurs.
class MEDIA_EXPORT PipelineController {
public:
enum class State {
CREATED,
STARTING,
PLAYING,
SEEKING,
SUSPENDING,
SUSPENDED,
RESUMING,
};
using RendererFactoryCB = base::Callback<std::unique_ptr<Renderer>(void)>;
using SeekedCB = base::Callback<void(bool time_updated)>;
using SuspendedCB = base::Callback<void()>;
using BeforeResumeCB = base::Callback<void()>;
using ResumedCB = base::Callback<void()>;
// Construct a PipelineController wrapping |pipeline_|.
// The callbacks are:
// - |renderer_factory_cb| is called by PipelineController to create new
// renderers when starting and resuming.
// - |seeked_cb| is called upon reaching a stable state if a seek occured.
// - |suspended_cb| is called immediately after suspending.
// - |before_resume_cb| is called immediately before resuming.
// - |resumed_cb| is called immediately after resuming.
// - |error_cb| is called if any operation on |pipeline_| does not result
// in PIPELINE_OK or its error callback is called.
PipelineController(std::unique_ptr<Pipeline> pipeline,
const RendererFactoryCB& renderer_factory_cb,
const SeekedCB& seeked_cb,
const SuspendedCB& suspended_cb,
const BeforeResumeCB& before_resume_cb,
const ResumedCB& resumed_cb,
const PipelineStatusCB& error_cb);
~PipelineController();
// Start |pipeline_|. |demuxer| will be retained and StartWaitingForSeek()/
// CancelPendingSeek() will be issued to it as necessary.
//
// When |is_streaming| is true, Resume() will always start at the
// beginning of the stream, rather than attempting to seek to the current
// time.
//
// When |is_static| is true, seeks to the current time may be elided.
// Otherwise it is assumed that the media data may have changed.
//
// The remaining parameters are just passed directly to pipeline_.Start().
void Start(Demuxer* demuxer,
Pipeline::Client* client,
bool is_streaming,
bool is_static);
// Request a seek to |time|. If |time_updated| is true, then the eventual
// |seeked_cb| callback will also have |time_updated| set to true; it
// indicates that the seek was requested by Blink and a time update is
// expected so that Blink can fire the seeked event.
void Seek(base::TimeDelta time, bool time_updated);
// Request that |pipeline_| be suspended. This is a no-op if |pipeline_| has
// been suspended.
void Suspend();
// Request that |pipeline_| be resumed. This is a no-op if |pipeline_| has not
// been suspended.
void Resume();
// Returns true if the current state is stable. This means that |state_| is
// PLAYING and there are no pending operations. Requests are processed
// immediately when the state is stable, otherwise they are queued.
//
// Exceptions to the above:
// - Start() is processed immediately while in the CREATED state.
// - Resume() is processed immediately while in the SUSPENDED state.
bool IsStable();
// Returns true if the current target state is suspended.
bool IsSuspended();
// Returns true if |pipeline_| is suspended.
bool IsPipelineSuspended();
// Subset of the Pipeline interface directly exposing |pipeline_|.
void Stop();
bool IsPipelineRunning() const;
double GetPlaybackRate() const;
void SetPlaybackRate(double playback_rate);
float GetVolume() const;
void SetVolume(float volume);
base::TimeDelta GetMediaTime() const;
Ranges<base::TimeDelta> GetBufferedTimeRanges() const;
base::TimeDelta GetMediaDuration() const;
bool DidLoadingProgress();
PipelineStatistics GetStatistics() const;
void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb);
void OnEnabledAudioTracksChanged(
const std::vector<MediaTrack::Id>& enabledTrackIds);
void OnSelectedVideoTrackChanged(
base::Optional<MediaTrack::Id> selected_track_id);
private:
// Attempts to make progress from the current state to the target state.
void Dispatch();
// PipelineStaus callback that also carries the target state.
void OnPipelineStatus(State state, PipelineStatus pipeline_status);
// The Pipeline we are managing state for.
std::unique_ptr<Pipeline> pipeline_;
// Factory for Renderers, used for Start() and Resume().
RendererFactoryCB renderer_factory_cb_;
// Called after seeks (which includes Start()) upon reaching a stable state.
// Multiple seeks result in only one callback if no stable state occurs
// between them.
SeekedCB seeked_cb_;
// Called immediately when |pipeline_| completes a suspend operation.
SuspendedCB suspended_cb_;
// Called immediately before |pipeline_| starts a resume operation.
ResumedCB before_resume_cb_;
// Called immediately when |pipeline_| completes a resume operation.
ResumedCB resumed_cb_;
// Called immediately when any operation on |pipeline_| results in an error.
PipelineStatusCB error_cb_;
// State for handling StartWaitingForSeek()/CancelPendingSeek().
Demuxer* demuxer_ = nullptr;
bool waiting_for_seek_ = false;
// When true, Resume() will start at time zero instead of seeking to the
// current time.
bool is_streaming_ = false;
// When true, seeking to the current time may be elided.
bool is_static_ = true;
// Tracks the current state of |pipeline_|.
State state_ = State::CREATED;
// Indicates that a seek has occurred. When set, a seeked callback will be
// issued at the next stable state.
bool pending_seeked_cb_ = false;
// Indicates that time has been changed by a seek, which will be reported at
// the next seeked callback.
bool pending_time_updated_ = false;
// The target time of the active seek; valid while SEEKING or RESUMING.
base::TimeDelta seek_time_;
// Target state which we will work to achieve. |pending_seek_time_| is only
// valid when |pending_seek_| is true.
bool pending_seek_ = false;
base::TimeDelta pending_seek_time_;
bool pending_suspend_ = false;
bool pending_resume_ = false;
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<PipelineController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PipelineController);
};
} // namespace media
#endif // MEDIA_FILTERS_PIPELINE_CONTROLLER_H_