OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 SERVICES_MEDIA_COMMON_RATE_CONTROL_BASE_H_ | |
6 #define SERVICES_MEDIA_COMMON_RATE_CONTROL_BASE_H_ | |
7 | |
8 #include <deque> | |
9 | |
10 #include "base/synchronization/lock.h" | |
11 #include "mojo/public/cpp/bindings/binding.h" | |
12 #include "mojo/services/media/common/cpp/linear_transform.h" | |
13 #include "mojo/services/media/common/interfaces/media_common.mojom.h" | |
14 #include "mojo/services/media/common/interfaces/rate_control.mojom.h" | |
15 | |
16 namespace mojo { | |
17 namespace media { | |
18 | |
19 class RateControlBase : public RateControl { | |
20 public: | |
21 // Default constructor and destructor | |
22 RateControlBase(); | |
23 ~RateControlBase() override; | |
24 | |
25 bool Bind(InterfaceRequest<RateControl> request); | |
26 bool is_bound() const { return binding_.is_bound(); } | |
27 | |
28 // Close any existing connections to clients, clear any pending rate changes | |
29 // and set the clock rate to 0/1. | |
30 void Reset(); | |
31 | |
32 // TODO(johngro): snapshotting the current transform requires an evaluation of | |
33 // all the pending timeline transformations. Currently, we allow users to | |
34 // schedule an arbitrary number of pending transformations. This could cause | |
35 // DoS hazards if a malicious (or just poorly written) application is | |
36 // schedules a ton of transformations, and then something like the mixer | |
37 // threads in the audio server is forced to collapse all of these | |
38 // transformations in order to mix then next set of outbound audio frames. | |
39 // | |
40 // A simple way to avoid this would be to allow the user to have only one | |
41 // pending transformation at any point in time. | |
42 // | |
43 // It would be nice to be able to simply return the transformation and use | |
44 // Rvalue references in calling code to access the temporary snapshot, but | |
45 // style does not permit us to use Rvalue references in such a way. | |
46 // | |
47 // Also; the way pending transformations get applied probably needs to be | |
48 // re-worked. Currently, when we snapshot, we collapse any pending | |
49 // transformations which should have occurred relative to LocalClock::now() | |
50 // into the current transformation. For both video and audio, however, we are | |
51 // always mixing/composing for a point in time in the near future, not for | |
52 // right now. We really want to given the mixer compositor a view of what the | |
53 // transformation is going to be at the mix/composition point, not what it is | |
54 // now. Additionally, since audio process many frames at a time, we need to | |
55 // give the audio mixer some knowledge of when we think the snapshotted | |
56 // transformation is going to change next. The audio mixer wants to mix up to | |
57 // that point, but not past it, and then fetch the new transformation before | |
58 // proceeding. | |
59 void SnapshotCurrentTransform(LinearTransform* out, | |
60 uint32_t* generation = nullptr); | |
61 | |
62 // RateControl interface | |
63 // | |
64 void GetCurrentTransform(const GetCurrentTransformCallback& cbk) override; | |
65 void SetTargetTimelineID(uint32_t id) override; | |
66 void SetCurrentQuad(TimelineQuadPtr quad) override; | |
67 void SetRate(uint32_t reference_delta, uint32_t target_delta) override; | |
68 void SetRateAtReferenceTime(uint32_t reference_delta, | |
69 uint32_t target_delta, | |
70 int64_t reference_time) override; | |
71 void SetRateAtTargetTime(uint32_t reference_delta, | |
72 uint32_t target_delta, | |
73 int64_t target_time) override; | |
74 void CancelPendingChanges() override; | |
75 | |
76 protected: | |
77 void ApplyPendingChangesLocked(int64_t target_now); | |
78 void AdvanceGenerationLocked() { | |
79 // bump the generation counter. Do not use the value 0. | |
80 while (!(++generation_)) {} | |
81 } | |
82 void OnIllegalRateChange(uint32_t numerator, uint32_t denominator); | |
83 | |
84 Binding<RateControl> binding_; | |
85 uint32_t target_timeline_id = TimelineTransform::kLocalTimeID; | |
86 | |
87 // Transformation state. | |
88 // | |
89 // Note: We use the LinearTransforms such that space A is the target timeline | |
90 // and space B is the reference timeline. Applying this convention, | |
91 // transforming from target to reference is the "forward" transformation and | |
92 // is always defined. Transforming from reference to target is the "reverse" | |
93 // transformation, and is only defined when we are not paused. | |
94 // <pedantic> | |
95 // OK; It is defined, but the equation has a singularity and the mapping is | |
96 // not 1-to-1. | |
97 // </pedantic>. | |
98 base::Lock transform_lock_; | |
99 LinearTransform current_transform_; | |
100 std::deque<LinearTransform> reference_pending_changes_; | |
101 std::deque<LinearTransform> target_pending_changes_; | |
102 uint32_t generation_ = 1; | |
103 }; | |
104 | |
105 } // namespace media | |
106 } // namespace mojo | |
107 | |
108 #endif // SERVICES_MEDIA_COMMON_RATE_CONTROL_BASE_H_ | |
OLD | NEW |