| 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 |