Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: chromecast/media/cma/base/balanced_media_task_runner_factory.cc

Issue 534893002: Introduce the concept of media task runner. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "chromecast/media/cma/base/media_task_runner.h"
14 #include "media/base/buffers.h"
15
16 namespace chromecast {
17 namespace media {
18
19 // MediaTaskRunnerWithNotification -
20 // Media task runner which also behaves as a media task runner observer.
21 class MediaTaskRunnerWithNotification
22 : public MediaTaskRunner {
xhwang 2014/09/03 17:06:39 fit in one line?
damienv1 2014/09/03 22:01:03 Done.
23 public:
24 MediaTaskRunnerWithNotification(
25 const scoped_refptr<MediaTaskRunner>& media_task_runner,
26 const base::Closure new_task_cb,
27 const base::Closure shutdown_cb);
xhwang 2014/09/03 17:06:39 Document what the two callbacks are and when they
damienv1 2014/09/03 22:01:03 Good catch. That's an unwilling mistake on my side
28
29 // MediaTaskRunner implementation.
30 virtual bool PostMediaTask(
31 const tracked_objects::Location& from_here,
32 const base::Closure& task,
33 base::TimeDelta timestamp) OVERRIDE;
34
35 private:
36 virtual ~MediaTaskRunnerWithNotification();
37
38 scoped_refptr<MediaTaskRunner> const media_task_runner_;
39
40 const base::Closure new_task_cb_;
41 const base::Closure shutdown_cb_;
42
43 DISALLOW_COPY_AND_ASSIGN(MediaTaskRunnerWithNotification);
44 };
45
46 MediaTaskRunnerWithNotification::MediaTaskRunnerWithNotification(
47 const scoped_refptr<MediaTaskRunner>& media_task_runner,
48 const base::Closure new_task_cb,
49 const base::Closure shutdown_cb)
50 : media_task_runner_(media_task_runner),
51 new_task_cb_(new_task_cb),
52 shutdown_cb_(shutdown_cb) {
53 }
54
55 MediaTaskRunnerWithNotification::~MediaTaskRunnerWithNotification() {
56 shutdown_cb_.Run();
57 }
58
59 bool MediaTaskRunnerWithNotification::PostMediaTask(
60 const tracked_objects::Location& from_here,
61 const base::Closure& task,
62 base::TimeDelta timestamp) {
63 bool may_run_in_future =
64 media_task_runner_->PostMediaTask(from_here, task, timestamp);
65 if (may_run_in_future)
66 new_task_cb_.Run();
67 return may_run_in_future;
68 }
69
70
71 // BalancedMediaTaskRunner -
72 // Run media tasks whose timestamp is less or equal to a max timestamp.
73 //
74 // Restrictions of BalancedMediaTaskRunner:
75 // - Can have at most one task in the queue.
76 // - Tasks should be given by increasing timestamps.
77 class BalancedMediaTaskRunner
78 : public MediaTaskRunner {
79 public:
80 explicit BalancedMediaTaskRunner(
81 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
82
83 // Schedule tasks whose timestamp is less than or equal to |max_timestamp|.
84 void ScheduleWork(base::TimeDelta max_timestamp);
85
86 // Return the timestamp of the last media task.
87 // Return ::media::kNoTimestamp() if no media task has been posted.
88 base::TimeDelta GetMediaTimestamp() const;
89
90 // MediaTaskRunner implementation.
91 virtual bool PostMediaTask(
92 const tracked_objects::Location& from_here,
93 const base::Closure& task,
94 base::TimeDelta timestamp) OVERRIDE;
95
96 private:
97 virtual ~BalancedMediaTaskRunner();
98
99 scoped_refptr<base::SingleThreadTaskRunner> const task_runner_;
100
101 // Protects the following variables.
102 mutable base::Lock lock_;
103
104 // Possible pending media task.
105 tracked_objects::Location from_here_;
106 base::Closure pending_task_;
107
108 // Timestamp of the last posted task.
109 // Is initialized to ::media::kNoTimestamp().
110 base::TimeDelta last_timestamp_;
111
112 DISALLOW_COPY_AND_ASSIGN(BalancedMediaTaskRunner);
113 };
114
115 BalancedMediaTaskRunner::BalancedMediaTaskRunner(
116 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
117 : task_runner_(task_runner),
118 last_timestamp_(::media::kNoTimestamp()) {
119 }
120
121 BalancedMediaTaskRunner::~BalancedMediaTaskRunner() {
122 }
123
124 void BalancedMediaTaskRunner::ScheduleWork(base::TimeDelta max_media_time) {
125 base::Closure task;
126 {
127 base::AutoLock auto_lock(lock_);
128 if (pending_task_.is_null())
129 return;
130
131 if (last_timestamp_ != ::media::kNoTimestamp() &&
132 last_timestamp_ >= max_media_time) {
133 return;
134 }
135
136 task = base::ResetAndReturn(&pending_task_);
137 }
138 task_runner_->PostTask(from_here_, task);
139 }
140
141 base::TimeDelta BalancedMediaTaskRunner::GetMediaTimestamp() const {
142 base::AutoLock auto_lock(lock_);
143 return last_timestamp_;
144 }
145
146 bool BalancedMediaTaskRunner::PostMediaTask(
147 const tracked_objects::Location& from_here,
148 const base::Closure& task,
149 base::TimeDelta timestamp) {
150 DCHECK(!task.is_null());
151
152 // Pass through for a task with no timestamp.
153 if (timestamp == ::media::kNoTimestamp()) {
154 return task_runner_->PostTask(from_here, task);
155 }
156
157 base::AutoLock auto_lock(lock_);
158
159 // Timestamps must be in order.
160 // Any task that does not meet that condition is simply discarded.
161 if (last_timestamp_ != ::media::kNoTimestamp() &&
162 timestamp < last_timestamp_) {
163 return false;
164 }
165
166 // Only support one pending task at a time.
167 DCHECK(pending_task_.is_null());
168 from_here_ = from_here;
169 pending_task_ = task;
170 last_timestamp_ = timestamp;
171
172 return true;
173 }
174
175
176 BalancedMediaTaskRunnerFactory::BalancedMediaTaskRunnerFactory(
177 base::TimeDelta max_delta)
178 : max_delta_(max_delta) {
179 }
180
181 BalancedMediaTaskRunnerFactory::~BalancedMediaTaskRunnerFactory() {
182 }
183
184 scoped_refptr<MediaTaskRunner>
185 BalancedMediaTaskRunnerFactory::CreateMediaTaskRunner(
186 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
187 scoped_refptr<BalancedMediaTaskRunner> media_task_runner(
188 new BalancedMediaTaskRunner(task_runner));
189 scoped_refptr<MediaTaskRunnerWithNotification> media_task_runner_wrapper(
190 new MediaTaskRunnerWithNotification(
191 media_task_runner,
192 base::Bind(&BalancedMediaTaskRunnerFactory::OnNewTask, this),
193 base::Bind(
194 &BalancedMediaTaskRunnerFactory::UnregisterMediaTaskRunner,
195 this, media_task_runner)));
196 base::AutoLock auto_lock(lock_);
197 task_runners_.insert(media_task_runner);
198 return media_task_runner_wrapper;
199 }
200
201 void BalancedMediaTaskRunnerFactory::OnNewTask() {
202 typedef
203 std::multimap<base::TimeDelta, scoped_refptr<BalancedMediaTaskRunner> >
204 TaskRunnerMap;
205 TaskRunnerMap runnable_task_runner;
206
207 base::AutoLock auto_lock(lock_);
208
209 // Get the minimum timestamp among all streams.
210 for (MediaTaskRunnerSet::const_iterator it = task_runners_.begin();
211 it != task_runners_.end(); ++it) {
212 base::TimeDelta timestamp((*it)->GetMediaTimestamp());
213 if (timestamp == ::media::kNoTimestamp())
214 continue;
215 runnable_task_runner.insert(
216 std::pair<base::TimeDelta, scoped_refptr<BalancedMediaTaskRunner> >(
217 timestamp, *it));
218 }
219
220 // If there is no media task, just returns.
221 if (runnable_task_runner.empty())
222 return;
223
224 // Run tasks which meet the balancing criteria.
225 base::TimeDelta min_timestamp(runnable_task_runner.begin()->first);
226 base::TimeDelta max_timestamp = min_timestamp + max_delta_;
227 for (TaskRunnerMap::iterator it = runnable_task_runner.begin();
228 it != runnable_task_runner.end(); ++it) {
229 (*it).second->ScheduleWork(max_timestamp);
230 }
231 }
232
233 void BalancedMediaTaskRunnerFactory::UnregisterMediaTaskRunner(
234 const scoped_refptr<BalancedMediaTaskRunner>& media_task_runner) {
235 base::AutoLock auto_lock(lock_);
236 task_runners_.erase(media_task_runner);
237 }
238
239 } // namespace media
240 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698