Motown: Use new TimelineTransform and related definitions
1) Deleted rate_control.mojom and replaced with timelines.mojom and
timeline_controller.mojom.
2) Removed redundant functionality from MediaTimelineController etc.
3) Deleted rate_control_base.* rate control implementation and replaced
with timeline_control_site.* timeline control site implementation.
4) Moved mojo_publisher from factory_service to common so it can be used
by timeline_control_site.
5) Updated many dependencies thereof.
R=kulakowski@chromium.org
Review URL: https://codereview.chromium.org/1986303002 .
diff --git a/examples/audio_play_test/BUILD.gn b/examples/audio_play_test/BUILD.gn
index a710e28..bda93ca 100644
--- a/examples/audio_play_test/BUILD.gn
+++ b/examples/audio_play_test/BUILD.gn
@@ -19,6 +19,7 @@
"//mojo/services/media/audio/interfaces",
"//mojo/services/media/common/cpp",
"//mojo/services/media/common/interfaces",
+ "//mojo/services/media/core/interfaces",
"//mojo/services/network/interfaces",
]
@@ -34,6 +35,7 @@
"//mojo/services/media/audio/interfaces",
"//mojo/services/media/common/cpp",
"//mojo/services/media/common/interfaces",
+ "//mojo/services/media/core/interfaces",
]
sources = [
diff --git a/examples/audio_play_test/play_tone.cc b/examples/audio_play_test/play_tone.cc
index 3a0ebc1..025bdbb 100644
--- a/examples/audio_play_test/play_tone.cc
+++ b/examples/audio_play_test/play_tone.cc
@@ -16,7 +16,7 @@
#include "mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h"
#include "mojo/services/media/common/cpp/linear_transform.h"
#include "mojo/services/media/common/cpp/local_time.h"
-#include "mojo/services/media/common/interfaces/rate_control.mojom.h"
+#include "mojo/services/media/common/interfaces/timelines.mojom.h"
namespace mojo {
namespace media {
@@ -52,8 +52,8 @@
void OnConnectionError(const std::string& connection_name);
AudioServerPtr audio_server_;
- AudioTrackPtr audio_track_;
- RateControlPtr rate_control_;
+ AudioTrackPtr audio_track_;
+ TimelineConsumerPtr timeline_consumer_;
std::unique_ptr<CircularBufferMediaPipeAdapter> audio_pipe_;
bool clock_started_ = false;
@@ -64,7 +64,7 @@
};
void PlayToneApp::Quit() {
- rate_control_.reset();
+ timeline_consumer_.reset();
audio_pipe_.reset();
audio_track_.reset();
audio_server_.reset();
@@ -115,11 +115,12 @@
// TODO(johngro): do something useful with our capabilities description.
sink_desc.reset();
- // Grab the rate control interface for our audio renderer.
- audio_track_->GetRateControl(GetProxy(&rate_control_));
- rate_control_.set_connection_error_handler([this]() {
- OnConnectionError("rate_control");
- });
+ // Grab the timeline consumer interface for our audio renderer.
+ MediaTimelineControlSitePtr timeline_control_site;
+ audio_track_->GetTimelineControlSite(GetProxy(&timeline_control_site));
+ timeline_control_site->GetTimelineConsumer(GetProxy(&timeline_consumer_));
+ timeline_consumer_.set_connection_error_handler(
+ [this]() { OnConnectionError("timeline_consumer"); });
// Configure our sink for 16-bit 48KHz mono.
AudioTrackConfigurationPtr cfg = AudioTrackConfiguration::New();
@@ -204,20 +205,11 @@
}
if (!clock_started_) {
- // In theory, this could be done at compile time using std::ratio, but
- // std::ratio is prohibited.
- LinearTransform::Ratio audio_rate(SAMP_FREQ, 1);
- LinearTransform::Ratio local_time_rate(LocalDuration::period::num,
- LocalDuration::period::den);
- LinearTransform::Ratio rate;
- bool success = LinearTransform::Ratio::Compose(local_time_rate,
- audio_rate,
- &rate);
- MOJO_DCHECK(success); // assert that there was no loss of precision.
+ MOJO_LOG(INFO) << "Setting rate 1/1";
- MOJO_LOG(INFO) << "Setting rate " << rate;
-
- rate_control_->SetRate(rate.numerator, rate.denominator);
+ timeline_consumer_->SetTimelineTransform(
+ kUnspecifiedTime, 1, 1, kUnspecifiedTime, kUnspecifiedTime,
+ [](bool completed) {});
clock_started_ = true;
}
}
diff --git a/examples/audio_play_test/play_wav.cc b/examples/audio_play_test/play_wav.cc
index d5dc2e1..f5f11ea 100644
--- a/examples/audio_play_test/play_wav.cc
+++ b/examples/audio_play_test/play_wav.cc
@@ -128,7 +128,7 @@
AudioServerPtr audio_server_;
AudioTrackPtr audio_track_;
AudioPipePtr audio_pipe_;
- RateControlPtr rate_control_;
+ TimelineConsumerPtr timeline_consumer_;
AudioPacket audio_packet_;
PacketCbk playout_complete_cbk_;
NetworkServicePtr network_service_;
@@ -196,7 +196,7 @@
url_loader_.reset();
network_service_.reset();
audio_pipe_.reset();
- rate_control_.reset();
+ timeline_consumer_.reset();
audio_track_.reset();
audio_server_.reset();
}
@@ -290,11 +290,12 @@
MediaConsumerPtr media_pipe;
audio_track_->Configure(cfg.Pass(), GetProxy(&media_pipe));
- // Grab the rate control interface for our audio renderer.
- audio_track_->GetRateControl(GetProxy(&rate_control_));
- rate_control_.set_connection_error_handler([this]() {
- OnConnectionError("rate_control");
- });
+ // Grab the timeline consumer interface for our audio renderer.
+ MediaTimelineControlSitePtr timeline_control_site;
+ audio_track_->GetTimelineControlSite(GetProxy(&timeline_control_site));
+ timeline_control_site->GetTimelineConsumer(GetProxy(&timeline_consumer_));
+ timeline_consumer_.set_connection_error_handler(
+ [this]() { OnConnectionError("timeline_consumer"); });
// Set up our media pipe helper, configure its callback and water marks to
// kick off the playback process.
@@ -501,8 +502,9 @@
}
if (!clock_started_ && (audio_pipe_->AboveHiWater() || !payload_len_)) {
- LocalTime sched = LocalClock::now() + local_time::from_msec(50);
- rate_control_->SetRateAtTargetTime(1, 1, sched.time_since_epoch().count());
+ timeline_consumer_->SetTimelineTransform(
+ kUnspecifiedTime, 1, 1, kUnspecifiedTime, kUnspecifiedTime,
+ [](bool completed) {});
clock_started_ = true;
}
}
diff --git a/examples/media_test/media_test.cc b/examples/media_test/media_test.cc
index 3e78fe4..c1f0d19 100644
--- a/examples/media_test/media_test.cc
+++ b/examples/media_test/media_test.cc
@@ -4,8 +4,8 @@
#include "examples/media_test/media_test.h"
#include "mojo/public/cpp/application/connect.h"
-#include "mojo/services/media/common/cpp/linear_transform.h"
-#include "mojo/services/media/common/cpp/local_time.h"
+#include "mojo/services/media/common/cpp/timeline.h"
+#include "mojo/services/media/common/cpp/timeline_function.h"
#include "mojo/services/media/control/interfaces/media_factory.mojom.h"
namespace mojo {
@@ -35,10 +35,8 @@
MediaTest::~MediaTest() {}
int64_t MediaTest::position_ns() const {
- // Apply the transform to the current time.
- int64_t position;
- transform_.DoForwardTransform(LocalClock::now().time_since_epoch().count(),
- &position);
+ // Apply the timeline function to the current time.
+ int64_t position = timeline_function_(Timeline::local_now());
if (position < 0) {
position = 0;
@@ -62,15 +60,8 @@
previous_state_ = state_;
state_ = status->state;
- // Create a linear transform that translates local time to presentation
- // time. Note that 'reference' here refers to the presentation time, and
- // 'target' refers to the local time.
if (status->timeline_transform) {
- transform_ =
- LinearTransform(status->timeline_transform->quad->target_offset,
- status->timeline_transform->quad->reference_delta,
- status->timeline_transform->quad->target_delta,
- status->timeline_transform->quad->reference_offset);
+ timeline_function_ = status->timeline_transform.To<TimelineFunction>();
}
metadata_ = status->metadata.Pass();
diff --git a/examples/media_test/media_test.h b/examples/media_test/media_test.h
index 00ce340..da5473e 100644
--- a/examples/media_test/media_test.h
+++ b/examples/media_test/media_test.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/application/application_impl.h"
-#include "mojo/services/media/common/cpp/linear_transform.h"
+#include "mojo/services/media/common/cpp/timeline_function.h"
#include "mojo/services/media/common/interfaces/rate_control.mojom.h"
#include "mojo/services/media/control/interfaces/media_factory.mojom.h"
#include "mojo/services/media/control/interfaces/media_player.mojom.h"
@@ -63,7 +63,7 @@
MediaPlayerPtr media_player_;
MediaState previous_state_ = MediaState::UNPREPARED;
MediaState state_ = MediaState::UNPREPARED;
- LinearTransform transform_ = LinearTransform(0, 0, 1, 0);
+ TimelineFunction timeline_function_;
MediaMetadataPtr metadata_;
UpdateCallback update_callback_;
diff --git a/mojo/dart/packages/mojo_services/BUILD.gn b/mojo/dart/packages/mojo_services/BUILD.gn
index 80dc70c..28cd6fd 100644
--- a/mojo/dart/packages/mojo_services/BUILD.gn
+++ b/mojo/dart/packages/mojo_services/BUILD.gn
@@ -63,7 +63,6 @@
"lib/mojo/media/media_transport.mojom.dart",
"lib/mojo/media/media_type_converter.mojom.dart",
"lib/mojo/media/media_types.mojom.dart",
- "lib/mojo/media/rate_control.mojom.dart",
"lib/mojo/media/timeline_controller.mojom.dart",
"lib/mojo/native_viewport_event_dispatcher.mojom.dart",
"lib/mojo/navigation.mojom.dart",
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart
index f559530..df9cd3e 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart
@@ -9,7 +9,7 @@
import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer;
import 'package:mojo_services/mojo/media/media_transport.mojom.dart' as media_transport_mojom;
import 'package:mojo_services/mojo/media/media_types.mojom.dart' as media_types_mojom;
-import 'package:mojo_services/mojo/media/rate_control.mojom.dart' as rate_control_mojom;
+import 'package:mojo_services/mojo/media/timeline_controller.mojom.dart' as timeline_controller_mojom;
@@ -418,15 +418,15 @@
}
-class _AudioTrackGetRateControlParams extends bindings.Struct {
+class _AudioTrackGetTimelineControlSiteParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(16, 0)
];
- rate_control_mojom.RateControlInterfaceRequest rateControl = null;
+ Object timelineControlSite = null;
- _AudioTrackGetRateControlParams() : super(kVersions.last.size);
+ _AudioTrackGetTimelineControlSiteParams() : super(kVersions.last.size);
- static _AudioTrackGetRateControlParams deserialize(bindings.Message message) {
+ static _AudioTrackGetTimelineControlSiteParams deserialize(bindings.Message message) {
var decoder = new bindings.Decoder(message);
var result = decode(decoder);
if (decoder.excessHandles != null) {
@@ -435,11 +435,11 @@
return result;
}
- static _AudioTrackGetRateControlParams decode(bindings.Decoder decoder0) {
+ static _AudioTrackGetTimelineControlSiteParams decode(bindings.Decoder decoder0) {
if (decoder0 == null) {
return null;
}
- _AudioTrackGetRateControlParams result = new _AudioTrackGetRateControlParams();
+ _AudioTrackGetTimelineControlSiteParams result = new _AudioTrackGetTimelineControlSiteParams();
var mainDataHeader = decoder0.decodeStructDataHeader();
if (mainDataHeader.version <= kVersions.last.version) {
@@ -461,7 +461,7 @@
}
if (mainDataHeader.version >= 0) {
- result.rateControl = decoder0.decodeInterfaceRequest(8, false, rate_control_mojom.RateControlStub.newFromEndpoint);
+ result.timelineControlSite = decoder0.decodeInterfaceRequest(8, false, timeline_controller_mojom.MediaTimelineControlSiteStub.newFromEndpoint);
}
return result;
}
@@ -469,17 +469,17 @@
void encode(bindings.Encoder encoder) {
var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
try {
- encoder0.encodeInterfaceRequest(rateControl, 8, false);
+ encoder0.encodeInterfaceRequest(timelineControlSite, 8, false);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
- "rateControl of struct _AudioTrackGetRateControlParams: $e";
+ "timelineControlSite of struct _AudioTrackGetTimelineControlSiteParams: $e";
rethrow;
}
}
String toString() {
- return "_AudioTrackGetRateControlParams("
- "rateControl: $rateControl" ")";
+ return "_AudioTrackGetTimelineControlSiteParams("
+ "timelineControlSite: $timelineControlSite" ")";
}
Map toJson() {
@@ -562,7 +562,7 @@
const int _audioTrackMethodDescribeName = 0;
const int _audioTrackMethodConfigureName = 1;
-const int _audioTrackMethodGetRateControlName = 2;
+const int _audioTrackMethodGetTimelineControlSiteName = 2;
const int _audioTrackMethodSetGainName = 3;
class _AudioTrackServiceDescription implements service_describer.ServiceDescription {
@@ -599,8 +599,8 @@
return p;
}
dynamic describe([Function responseFactory = null]);
- void configure(AudioTrackConfiguration configuration, media_transport_mojom.MediaConsumerInterfaceRequest pipe);
- void getRateControl(rate_control_mojom.RateControlInterfaceRequest rateControl);
+ void configure(AudioTrackConfiguration configuration, Object pipe);
+ void getTimelineControlSite(Object timelineControlSite);
void setGain(double dbGain);
static const double kMutedGain = -160.0;
static const double kMaxGain = 20.0;
@@ -719,15 +719,15 @@
ctrl.sendMessage(params,
_audioTrackMethodConfigureName);
}
- void getRateControl(rate_control_mojom.RateControlInterfaceRequest rateControl) {
+ void getTimelineControlSite(Object timelineControlSite) {
if (!ctrl.isBound) {
ctrl.proxyError("The Proxy is closed.");
return;
}
- var params = new _AudioTrackGetRateControlParams();
- params.rateControl = rateControl;
+ var params = new _AudioTrackGetTimelineControlSiteParams();
+ params.timelineControlSite = timelineControlSite;
ctrl.sendMessage(params,
- _audioTrackMethodGetRateControlName);
+ _audioTrackMethodGetTimelineControlSiteName);
}
void setGain(double dbGain) {
if (!ctrl.isBound) {
@@ -804,10 +804,10 @@
message.payload);
_impl.configure(params.configuration, params.pipe);
break;
- case _audioTrackMethodGetRateControlName:
- var params = _AudioTrackGetRateControlParams.deserialize(
+ case _audioTrackMethodGetTimelineControlSiteName:
+ var params = _AudioTrackGetTimelineControlSiteParams.deserialize(
message.payload);
- _impl.getRateControl(params.rateControl);
+ _impl.getTimelineControlSite(params.timelineControlSite);
break;
case _audioTrackMethodSetGainName:
var params = _AudioTrackSetGainParams.deserialize(
@@ -878,8 +878,8 @@
void configure(AudioTrackConfiguration configuration, media_transport_mojom.MediaConsumerInterfaceRequest pipe) {
return impl.configure(configuration, pipe);
}
- void getRateControl(rate_control_mojom.RateControlInterfaceRequest rateControl) {
- return impl.getRateControl(rateControl);
+ void getTimelineControlSite(Object timelineControlSite) {
+ return impl.getTimelineControlSite(timelineControlSite);
}
void setGain(double dbGain) {
return impl.setGain(dbGain);
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/media/media_player.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/media/media_player.mojom.dart
index 5ab0c9e..d570d96 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/media/media_player.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/media/media_player.mojom.dart
@@ -9,7 +9,7 @@
import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer;
import 'package:mojo_services/mojo/media/media_metadata.mojom.dart' as media_metadata_mojom;
import 'package:mojo_services/mojo/media/media_state.mojom.dart' as media_state_mojom;
-import 'package:mojo_services/mojo/media/rate_control.mojom.dart' as rate_control_mojom;
+import 'package:mojo_services/mojo/timelines.mojom.dart' as timelines_mojom;
@@ -18,7 +18,7 @@
const bindings.StructDataHeader(32, 0)
];
media_state_mojom.MediaState state = null;
- rate_control_mojom.TimelineTransform timelineTransform = null;
+ timelines_mojom.TimelineTransform timelineTransform = null;
media_metadata_mojom.MediaMetadata metadata = null;
MediaPlayerStatus() : super(kVersions.last.size);
@@ -67,7 +67,7 @@
if (mainDataHeader.version >= 0) {
var decoder1 = decoder0.decodePointer(16, true);
- result.timelineTransform = rate_control_mojom.TimelineTransform.decode(decoder1);
+ result.timelineTransform = timelines_mojom.TimelineTransform.decode(decoder1);
}
if (mainDataHeader.version >= 0) {
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/media/media_sink.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/media/media_sink.mojom.dart
index b21bfb3..6b73e31 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/media/media_sink.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/media/media_sink.mojom.dart
@@ -9,7 +9,7 @@
import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer;
import 'package:mojo_services/mojo/media/media_state.mojom.dart' as media_state_mojom;
import 'package:mojo_services/mojo/media/media_transport.mojom.dart' as media_transport_mojom;
-import 'package:mojo_services/mojo/media/rate_control.mojom.dart' as rate_control_mojom;
+import 'package:mojo_services/mojo/timelines.mojom.dart' as timelines_mojom;
@@ -18,7 +18,7 @@
const bindings.StructDataHeader(24, 0)
];
media_state_mojom.MediaState state = null;
- rate_control_mojom.TimelineTransform timelineTransform = null;
+ timelines_mojom.TimelineTransform timelineTransform = null;
MediaSinkStatus() : super(kVersions.last.size);
@@ -66,7 +66,7 @@
if (mainDataHeader.version >= 0) {
var decoder1 = decoder0.decodePointer(16, true);
- result.timelineTransform = rate_control_mojom.TimelineTransform.decode(decoder1);
+ result.timelineTransform = timelines_mojom.TimelineTransform.decode(decoder1);
}
return result;
}
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/media/timeline_controller.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/media/timeline_controller.mojom.dart
index 4ab5371..8ea67ec 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/media/timeline_controller.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/media/timeline_controller.mojom.dart
@@ -11,100 +11,13 @@
-class MediaTimelineControllerStatus extends bindings.Struct {
+class MediaTimelineControlSiteStatus extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(24, 0)
];
timelines_mojom.TimelineTransform timelineTransform = null;
bool endOfStream = false;
- MediaTimelineControllerStatus() : super(kVersions.last.size);
-
- static MediaTimelineControllerStatus deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static MediaTimelineControllerStatus decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- MediaTimelineControllerStatus result = new MediaTimelineControllerStatus();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- var decoder1 = decoder0.decodePointer(8, false);
- result.timelineTransform = timelines_mojom.TimelineTransform.decode(decoder1);
- }
- if (mainDataHeader.version >= 0) {
-
- result.endOfStream = decoder0.decodeBool(16, 0);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeStruct(timelineTransform, 8, false);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "timelineTransform of struct MediaTimelineControllerStatus: $e";
- rethrow;
- }
- try {
- encoder0.encodeBool(endOfStream, 16, 0);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "endOfStream of struct MediaTimelineControllerStatus: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "MediaTimelineControllerStatus("
- "timelineTransform: $timelineTransform" ", "
- "endOfStream: $endOfStream" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["timelineTransform"] = timelineTransform;
- map["endOfStream"] = endOfStream;
- return map;
- }
-}
-
-
-class MediaTimelineControlSiteStatus extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(16, 0)
- ];
- bool endOfStream = false;
- bool starving = false;
-
MediaTimelineControlSiteStatus() : super(kVersions.last.size);
static MediaTimelineControlSiteStatus deserialize(bindings.Message message) {
@@ -142,11 +55,12 @@
}
if (mainDataHeader.version >= 0) {
- result.endOfStream = decoder0.decodeBool(8, 0);
+ var decoder1 = decoder0.decodePointer(8, false);
+ result.timelineTransform = timelines_mojom.TimelineTransform.decode(decoder1);
}
if (mainDataHeader.version >= 0) {
- result.starving = decoder0.decodeBool(8, 1);
+ result.endOfStream = decoder0.decodeBool(16, 0);
}
return result;
}
@@ -154,31 +68,31 @@
void encode(bindings.Encoder encoder) {
var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
try {
- encoder0.encodeBool(endOfStream, 8, 0);
+ encoder0.encodeStruct(timelineTransform, 8, false);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
- "endOfStream of struct MediaTimelineControlSiteStatus: $e";
+ "timelineTransform of struct MediaTimelineControlSiteStatus: $e";
rethrow;
}
try {
- encoder0.encodeBool(starving, 8, 1);
+ encoder0.encodeBool(endOfStream, 16, 0);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
- "starving of struct MediaTimelineControlSiteStatus: $e";
+ "endOfStream of struct MediaTimelineControlSiteStatus: $e";
rethrow;
}
}
String toString() {
return "MediaTimelineControlSiteStatus("
- "endOfStream: $endOfStream" ", "
- "starving: $starving" ")";
+ "timelineTransform: $timelineTransform" ", "
+ "endOfStream: $endOfStream" ")";
}
Map toJson() {
Map map = new Map();
+ map["timelineTransform"] = timelineTransform;
map["endOfStream"] = endOfStream;
- map["starving"] = starving;
return map;
}
}
@@ -255,365 +169,6 @@
}
-class _MediaTimelineControllerGetStatusParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(16, 0)
- ];
- int versionLastSeen = 0;
-
- _MediaTimelineControllerGetStatusParams() : super(kVersions.last.size);
-
- static _MediaTimelineControllerGetStatusParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static _MediaTimelineControllerGetStatusParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- _MediaTimelineControllerGetStatusParams result = new _MediaTimelineControllerGetStatusParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- result.versionLastSeen = decoder0.decodeUint64(8);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeUint64(versionLastSeen, 8);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "versionLastSeen of struct _MediaTimelineControllerGetStatusParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "_MediaTimelineControllerGetStatusParams("
- "versionLastSeen: $versionLastSeen" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["versionLastSeen"] = versionLastSeen;
- return map;
- }
-}
-
-
-class MediaTimelineControllerGetStatusResponseParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(24, 0)
- ];
- int version = 0;
- MediaTimelineControllerStatus status = null;
-
- MediaTimelineControllerGetStatusResponseParams() : super(kVersions.last.size);
-
- static MediaTimelineControllerGetStatusResponseParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static MediaTimelineControllerGetStatusResponseParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- MediaTimelineControllerGetStatusResponseParams result = new MediaTimelineControllerGetStatusResponseParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- result.version = decoder0.decodeUint64(8);
- }
- if (mainDataHeader.version >= 0) {
-
- var decoder1 = decoder0.decodePointer(16, false);
- result.status = MediaTimelineControllerStatus.decode(decoder1);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeUint64(version, 8);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "version of struct MediaTimelineControllerGetStatusResponseParams: $e";
- rethrow;
- }
- try {
- encoder0.encodeStruct(status, 16, false);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "status of struct MediaTimelineControllerGetStatusResponseParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "MediaTimelineControllerGetStatusResponseParams("
- "version: $version" ", "
- "status: $status" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["version"] = version;
- map["status"] = status;
- return map;
- }
-}
-
-
-class _MediaTimelineControllerSetTimelineTransformParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(40, 0)
- ];
- int subjectTime = 0;
- int subjectDelta = 0;
- int referenceDelta = 0;
- int effectiveSubjectTime = 0;
- int effectiveReferenceTime = 0;
-
- _MediaTimelineControllerSetTimelineTransformParams() : super(kVersions.last.size);
-
- static _MediaTimelineControllerSetTimelineTransformParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static _MediaTimelineControllerSetTimelineTransformParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- _MediaTimelineControllerSetTimelineTransformParams result = new _MediaTimelineControllerSetTimelineTransformParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- result.subjectTime = decoder0.decodeInt64(8);
- }
- if (mainDataHeader.version >= 0) {
-
- result.subjectDelta = decoder0.decodeUint32(16);
- }
- if (mainDataHeader.version >= 0) {
-
- result.referenceDelta = decoder0.decodeUint32(20);
- }
- if (mainDataHeader.version >= 0) {
-
- result.effectiveSubjectTime = decoder0.decodeInt64(24);
- }
- if (mainDataHeader.version >= 0) {
-
- result.effectiveReferenceTime = decoder0.decodeInt64(32);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeInt64(subjectTime, 8);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "subjectTime of struct _MediaTimelineControllerSetTimelineTransformParams: $e";
- rethrow;
- }
- try {
- encoder0.encodeUint32(subjectDelta, 16);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "subjectDelta of struct _MediaTimelineControllerSetTimelineTransformParams: $e";
- rethrow;
- }
- try {
- encoder0.encodeUint32(referenceDelta, 20);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "referenceDelta of struct _MediaTimelineControllerSetTimelineTransformParams: $e";
- rethrow;
- }
- try {
- encoder0.encodeInt64(effectiveSubjectTime, 24);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "effectiveSubjectTime of struct _MediaTimelineControllerSetTimelineTransformParams: $e";
- rethrow;
- }
- try {
- encoder0.encodeInt64(effectiveReferenceTime, 32);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "effectiveReferenceTime of struct _MediaTimelineControllerSetTimelineTransformParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "_MediaTimelineControllerSetTimelineTransformParams("
- "subjectTime: $subjectTime" ", "
- "subjectDelta: $subjectDelta" ", "
- "referenceDelta: $referenceDelta" ", "
- "effectiveSubjectTime: $effectiveSubjectTime" ", "
- "effectiveReferenceTime: $effectiveReferenceTime" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["subjectTime"] = subjectTime;
- map["subjectDelta"] = subjectDelta;
- map["referenceDelta"] = referenceDelta;
- map["effectiveSubjectTime"] = effectiveSubjectTime;
- map["effectiveReferenceTime"] = effectiveReferenceTime;
- return map;
- }
-}
-
-
-class MediaTimelineControllerSetTimelineTransformResponseParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(16, 0)
- ];
- bool completed = false;
-
- MediaTimelineControllerSetTimelineTransformResponseParams() : super(kVersions.last.size);
-
- static MediaTimelineControllerSetTimelineTransformResponseParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static MediaTimelineControllerSetTimelineTransformResponseParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- MediaTimelineControllerSetTimelineTransformResponseParams result = new MediaTimelineControllerSetTimelineTransformResponseParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- result.completed = decoder0.decodeBool(8, 0);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeBool(completed, 8, 0);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "completed of struct MediaTimelineControllerSetTimelineTransformResponseParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "MediaTimelineControllerSetTimelineTransformResponseParams("
- "completed: $completed" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["completed"] = completed;
- return map;
- }
-}
-
-
class _MediaTimelineControllerGetControlSiteParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(16, 0)
@@ -915,9 +470,7 @@
}
const int _mediaTimelineControllerMethodAddControlSiteName = 0;
-const int _mediaTimelineControllerMethodGetStatusName = 1;
-const int _mediaTimelineControllerMethodSetTimelineTransformName = 2;
-const int _mediaTimelineControllerMethodGetControlSiteName = 3;
+const int _mediaTimelineControllerMethodGetControlSiteName = 1;
class _MediaTimelineControllerServiceDescription implements service_describer.ServiceDescription {
dynamic getTopLevelInterface([Function responseFactory]) =>
@@ -932,50 +485,8 @@
abstract class MediaTimelineController {
static const String serviceName = null;
-
- static service_describer.ServiceDescription _cachedServiceDescription;
- static service_describer.ServiceDescription get serviceDescription {
- if (_cachedServiceDescription == null) {
- _cachedServiceDescription = new _MediaTimelineControllerServiceDescription();
- }
- return _cachedServiceDescription;
- }
-
- static MediaTimelineControllerProxy connectToService(
- bindings.ServiceConnector s, String url, [String serviceName]) {
- MediaTimelineControllerProxy p = new MediaTimelineControllerProxy.unbound();
- String name = serviceName ?? MediaTimelineController.serviceName;
- if ((name == null) || name.isEmpty) {
- throw new core.MojoApiError(
- "If an interface has no ServiceName, then one must be provided.");
- }
- s.connectToService(url, p, name);
- return p;
- }
- void addControlSite(MediaTimelineControlSiteInterface controlSite);
- dynamic getStatus(int versionLastSeen,[Function responseFactory = null]);
- dynamic setTimelineTransform(int subjectTime,int subjectDelta,int referenceDelta,int effectiveSubjectTime,int effectiveReferenceTime,[Function responseFactory = null]);
- void getControlSite(MediaTimelineControlSiteInterfaceRequest controlSite);
- static const int kUnspecifiedTime = 9223372036854775807;
- static const int kInitialStatus = 0;
-}
-
-abstract class MediaTimelineControllerInterface
- implements bindings.MojoInterface<MediaTimelineController>,
- MediaTimelineController {
- factory MediaTimelineControllerInterface([MediaTimelineController impl]) =>
- new MediaTimelineControllerStub.unbound(impl);
- factory MediaTimelineControllerInterface.fromEndpoint(
- core.MojoMessagePipeEndpoint endpoint,
- [MediaTimelineController impl]) =>
- new MediaTimelineControllerStub.fromEndpoint(endpoint, impl);
-}
-
-abstract class MediaTimelineControllerInterfaceRequest
- implements bindings.MojoInterface<MediaTimelineController>,
- MediaTimelineController {
- factory MediaTimelineControllerInterfaceRequest() =>
- new MediaTimelineControllerProxy.unbound();
+ void addControlSite(Object controlSite);
+ void getControlSite(Object controlSite);
}
class _MediaTimelineControllerProxyControl
@@ -993,46 +504,6 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
- case _mediaTimelineControllerMethodGetStatusName:
- var r = MediaTimelineControllerGetStatusResponseParams.deserialize(
- message.payload);
- if (!message.header.hasRequestId) {
- proxyError("Expected a message with a valid request Id.");
- return;
- }
- Completer c = completerMap[message.header.requestId];
- if (c == null) {
- proxyError(
- "Message had unknown request Id: ${message.header.requestId}");
- return;
- }
- completerMap.remove(message.header.requestId);
- if (c.isCompleted) {
- proxyError("Response completer already completed");
- return;
- }
- c.complete(r);
- break;
- case _mediaTimelineControllerMethodSetTimelineTransformName:
- var r = MediaTimelineControllerSetTimelineTransformResponseParams.deserialize(
- message.payload);
- if (!message.header.hasRequestId) {
- proxyError("Expected a message with a valid request Id.");
- return;
- }
- Completer c = completerMap[message.header.requestId];
- if (c == null) {
- proxyError(
- "Message had unknown request Id: ${message.header.requestId}");
- return;
- }
- completerMap.remove(message.header.requestId);
- if (c.isCompleted) {
- proxyError("Response completer already completed");
- return;
- }
- c.complete(r);
- break;
default:
proxyError("Unexpected message type: ${message.header.type}");
close(immediate: true);
@@ -1084,29 +555,7 @@
ctrl.sendMessage(params,
_mediaTimelineControllerMethodAddControlSiteName);
}
- dynamic getStatus(int versionLastSeen,[Function responseFactory = null]) {
- var params = new _MediaTimelineControllerGetStatusParams();
- params.versionLastSeen = versionLastSeen;
- return ctrl.sendMessageWithRequestId(
- params,
- _mediaTimelineControllerMethodGetStatusName,
- -1,
- bindings.MessageHeader.kMessageExpectsResponse);
- }
- dynamic setTimelineTransform(int subjectTime,int subjectDelta,int referenceDelta,int effectiveSubjectTime,int effectiveReferenceTime,[Function responseFactory = null]) {
- var params = new _MediaTimelineControllerSetTimelineTransformParams();
- params.subjectTime = subjectTime;
- params.subjectDelta = subjectDelta;
- params.referenceDelta = referenceDelta;
- params.effectiveSubjectTime = effectiveSubjectTime;
- params.effectiveReferenceTime = effectiveReferenceTime;
- return ctrl.sendMessageWithRequestId(
- params,
- _mediaTimelineControllerMethodSetTimelineTransformName,
- -1,
- bindings.MessageHeader.kMessageExpectsResponse);
- }
- void getControlSite(MediaTimelineControlSiteInterfaceRequest controlSite) {
+ void getControlSite(Object controlSite) {
if (!ctrl.isBound) {
ctrl.proxyError("The Proxy is closed.");
return;
@@ -1140,17 +589,6 @@
String get serviceName => MediaTimelineController.serviceName;
- MediaTimelineControllerGetStatusResponseParams _mediaTimelineControllerGetStatusResponseParamsFactory(int version, MediaTimelineControllerStatus status) {
- var result = new MediaTimelineControllerGetStatusResponseParams();
- result.version = version;
- result.status = status;
- return result;
- }
- MediaTimelineControllerSetTimelineTransformResponseParams _mediaTimelineControllerSetTimelineTransformResponseParamsFactory(bool completed) {
- var result = new MediaTimelineControllerSetTimelineTransformResponseParams();
- result.completed = completed;
- return result;
- }
dynamic handleMessage(bindings.ServiceMessage message) {
if (bindings.ControlMessageHandler.isControlMessage(message)) {
@@ -1167,50 +605,6 @@
message.payload);
_impl.addControlSite(params.controlSite);
break;
- case _mediaTimelineControllerMethodGetStatusName:
- var params = _MediaTimelineControllerGetStatusParams.deserialize(
- message.payload);
- var response = _impl.getStatus(params.versionLastSeen,_mediaTimelineControllerGetStatusResponseParamsFactory);
- if (response is Future) {
- return response.then((response) {
- if (response != null) {
- return buildResponseWithId(
- response,
- _mediaTimelineControllerMethodGetStatusName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- });
- } else if (response != null) {
- return buildResponseWithId(
- response,
- _mediaTimelineControllerMethodGetStatusName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- break;
- case _mediaTimelineControllerMethodSetTimelineTransformName:
- var params = _MediaTimelineControllerSetTimelineTransformParams.deserialize(
- message.payload);
- var response = _impl.setTimelineTransform(params.subjectTime,params.subjectDelta,params.referenceDelta,params.effectiveSubjectTime,params.effectiveReferenceTime,_mediaTimelineControllerSetTimelineTransformResponseParamsFactory);
- if (response is Future) {
- return response.then((response) {
- if (response != null) {
- return buildResponseWithId(
- response,
- _mediaTimelineControllerMethodSetTimelineTransformName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- });
- } else if (response != null) {
- return buildResponseWithId(
- response,
- _mediaTimelineControllerMethodSetTimelineTransformName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- break;
case _mediaTimelineControllerMethodGetControlSiteName:
var params = _MediaTimelineControllerGetControlSiteParams.deserialize(
message.payload);
@@ -1277,13 +671,7 @@
void addControlSite(MediaTimelineControlSiteInterface controlSite) {
return impl.addControlSite(controlSite);
}
- dynamic getStatus(int versionLastSeen,[Function responseFactory = null]) {
- return impl.getStatus(versionLastSeen,responseFactory);
- }
- dynamic setTimelineTransform(int subjectTime,int subjectDelta,int referenceDelta,int effectiveSubjectTime,int effectiveReferenceTime,[Function responseFactory = null]) {
- return impl.setTimelineTransform(subjectTime,subjectDelta,referenceDelta,effectiveSubjectTime,effectiveReferenceTime,responseFactory);
- }
- void getControlSite(MediaTimelineControlSiteInterfaceRequest controlSite) {
+ void getControlSite(Object controlSite) {
return impl.getControlSite(controlSite);
}
}
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/timelines.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/timelines.mojom.dart
index 639bb64..6381061 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/timelines.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/timelines.mojom.dart
@@ -7,6 +7,7 @@
import 'package:mojo/bindings.dart' as bindings;
import 'package:mojo/core.dart' as core;
import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer;
+const int kUnspecifiedTime = 9223372036854775807;
@@ -359,7 +360,6 @@
return p;
}
dynamic setTimelineTransform(int subjectTime,int referenceDelta,int subjectDelta,int effectiveReferenceTime,int effectiveSubjectTime,[Function responseFactory = null]);
- static const int kUnspecifiedTime = 9223372036854775807;
}
abstract class TimelineConsumerInterface
diff --git a/mojo/services/media/audio/interfaces/audio_track.mojom b/mojo/services/media/audio/interfaces/audio_track.mojom
index b9f251e..b5cf803 100644
--- a/mojo/services/media/audio/interfaces/audio_track.mojom
+++ b/mojo/services/media/audio/interfaces/audio_track.mojom
@@ -8,7 +8,7 @@
import "mojo/services/media/common/interfaces/media_common.mojom";
import "mojo/services/media/common/interfaces/media_transport.mojom";
import "mojo/services/media/common/interfaces/media_types.mojom";
-import "mojo/services/media/common/interfaces/rate_control.mojom";
+import "mojo/services/media/core/interfaces/timeline_controller.mojom";
struct AudioTrackDescriptor {
// The track supports the union of all these media type sets.
@@ -50,8 +50,8 @@
// Set the configuration, receive a pipe to send data to in return.
Configure(AudioTrackConfiguration configuration, MediaConsumer& pipe);
- // Request the rate control interface for this AudioTrack
- GetRateControl(RateControl& rate_control);
+ // Request the timeline control site for this AudioTrack
+ GetTimelineControlSite(MediaTimelineControlSite& timeline_control_site);
// Sets the current gain/attenuation of the track, expressed in dB. Legal
// values are in the range [-inf, 20.0]. Any value less than or equal to the
diff --git a/mojo/services/media/common/cpp/BUILD.gn b/mojo/services/media/common/cpp/BUILD.gn
index c2f6b70..42272a0 100644
--- a/mojo/services/media/common/cpp/BUILD.gn
+++ b/mojo/services/media/common/cpp/BUILD.gn
@@ -19,6 +19,7 @@
"mapped_shared_buffer.h",
"shared_media_buffer_allocator.cc",
"shared_media_buffer_allocator.h",
+ "timeline.h",
"timeline_function.cc",
"timeline_function.h",
"timeline_rate.cc",
diff --git a/mojo/services/media/common/cpp/timeline.h b/mojo/services/media/common/cpp/timeline.h
new file mode 100644
index 0000000..4fc3651
--- /dev/null
+++ b/mojo/services/media/common/cpp/timeline.h
@@ -0,0 +1,53 @@
+// 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 MOJO_SERVICES_MEDIA_COMMON_CPP_TIMELINE_H_
+#define MOJO_SERVICES_MEDIA_COMMON_CPP_TIMELINE_H_
+
+#include <stdint.h>
+#include <chrono> // NOLINT(build/c++11)
+
+// TODO(johngro): As we add support for other environments, extend this list.
+#if defined(OS_POSIX)
+#include "mojo/services/media/common/cpp/platform/posix/local_time.h"
+#else
+// TODO(johngro): consider adding a #warning or #info to inform the user that
+// they are using the generic implementation of LocalTime, and really should get
+// around to implementing proper platform support ASAP.
+#include "mojo/services/media/common/cpp/platform/generic/local_time.h"
+#endif
+
+namespace mojo {
+namespace media {
+
+// Some helpful constants and static methods relating to timelines.
+class Timeline {
+ public:
+ // Returns the current local time in nanoseconds since epoch.
+ static int64_t local_now() {
+ return local_time::Clock::now().time_since_epoch().count();
+ }
+
+ template <typename T>
+ static constexpr int64_t ns_from_seconds(T seconds) {
+ return static_cast<int64_t>(seconds * std::nano::den);
+ }
+
+ template <typename T>
+ static constexpr int64_t ns_from_ms(T milliseconds) {
+ return static_cast<int64_t>(milliseconds *
+ (std::nano::den / std::milli::den));
+ }
+
+ template <typename T>
+ static constexpr int64_t ns_from_us(T microseconds) {
+ return static_cast<int64_t>(microseconds *
+ (std::nano::den / std::micro::den));
+ }
+};
+
+} // namespace media
+} // namespace mojo
+
+#endif // MOJO_SERVICES_MEDIA_COMMON_CPP_TIMELINE_H_
diff --git a/mojo/services/media/common/cpp/timeline_function.cc b/mojo/services/media/common/cpp/timeline_function.cc
index 350fde6..f2b1ec1 100644
--- a/mojo/services/media/common/cpp/timeline_function.cc
+++ b/mojo/services/media/common/cpp/timeline_function.cc
@@ -29,4 +29,25 @@
}
} // namespace media
+
+TimelineTransformPtr
+TypeConverter<TimelineTransformPtr, media::TimelineFunction>::Convert(
+ const media::TimelineFunction& input) {
+ TimelineTransformPtr result = TimelineTransform::New();
+ result->reference_time = input.reference_time();
+ result->subject_time = input.subject_time();
+ result->reference_delta = input.reference_delta();
+ result->subject_delta = input.subject_delta();
+ return result;
+}
+
+media::TimelineFunction
+TypeConverter<media::TimelineFunction, TimelineTransformPtr>::Convert(
+ const TimelineTransformPtr& input) {
+ return input ? media::TimelineFunction(
+ input->reference_time, input->subject_time,
+ input->reference_delta, input->subject_delta)
+ : media::TimelineFunction();
+}
+
} // namespace mojo
diff --git a/mojo/services/media/common/cpp/timeline_function.h b/mojo/services/media/common/cpp/timeline_function.h
index 67ac80a..075ee01 100644
--- a/mojo/services/media/common/cpp/timeline_function.h
+++ b/mojo/services/media/common/cpp/timeline_function.h
@@ -5,8 +5,10 @@
#ifndef MOJO_SERVICES_MEDIA_COMMON_CPP_TIMELINE_FUNCTION_H_
#define MOJO_SERVICES_MEDIA_COMMON_CPP_TIMELINE_FUNCTION_H_
+#include "mojo/public/cpp/bindings/type_converter.h"
#include "mojo/public/cpp/environment/logging.h"
#include "mojo/services/media/common/cpp/timeline_rate.h"
+#include "mojo/services/media/common/interfaces/timelines.mojom.h"
namespace mojo {
namespace media {
@@ -128,6 +130,19 @@
}
} // namespace media
+
+template <>
+struct TypeConverter<TimelineTransformPtr, media::TimelineFunction> {
+ static TimelineTransformPtr Convert(
+ const media::TimelineFunction& input);
+};
+
+template <>
+struct TypeConverter<media::TimelineFunction, TimelineTransformPtr> {
+ static media::TimelineFunction Convert(
+ const TimelineTransformPtr& input);
+};
+
} // namespace mojo
#endif // MOJO_SERVICES_MEDIA_COMMON_CPP_TIMELINE_FUNCTION_H_
diff --git a/mojo/services/media/common/cpp/timeline_rate.h b/mojo/services/media/common/cpp/timeline_rate.h
index 7aa0216..4718f1f 100644
--- a/mojo/services/media/common/cpp/timeline_rate.h
+++ b/mojo/services/media/common/cpp/timeline_rate.h
@@ -62,6 +62,25 @@
explicit TimelineRate(uint32_t subject_delta)
: subject_delta_(subject_delta), reference_delta_(1) {}
+ explicit TimelineRate(float rate_as_float)
+ : subject_delta_(
+ rate_as_float > 1.0f
+ ? kFloatFactor
+ : static_cast<uint32_t>(kFloatFactor * rate_as_float)),
+ reference_delta_(
+ rate_as_float > 1.0f
+ ? static_cast<uint32_t>(kFloatFactor / rate_as_float)
+ : kFloatFactor) {
+ // The expressions above are intended to provide good precision for
+ // 'reasonable' playback rate values (say in the range 0.0 to 4.0). The
+ // expressions always produce a ratio of kFloatFactor and a number smaller
+ // than kFloatFactor. kFloatFactor's value was chosen because floats have
+ // a 23-bit mantissa, and operations with a larger factor would sacrifice
+ // precision.
+ MOJO_DCHECK(rate_as_float >= 0.0f);
+ Reduce(&subject_delta_, &reference_delta_);
+ }
+
TimelineRate(uint32_t subject_delta, uint32_t reference_delta)
: subject_delta_(subject_delta), reference_delta_(reference_delta) {
MOJO_DCHECK(reference_delta != 0);
@@ -84,6 +103,10 @@
uint32_t reference_delta() const { return reference_delta_; }
private:
+ // A multiplier for float-to-TimelineRate conversions chosen because floats
+ // have a 23-bit mantissa.
+ static constexpr uint32_t kFloatFactor = 1ul << 23;
+
uint32_t subject_delta_;
uint32_t reference_delta_;
};
diff --git a/mojo/services/media/common/interfaces/BUILD.gn b/mojo/services/media/common/interfaces/BUILD.gn
index 109f979..ffdb131 100644
--- a/mojo/services/media/common/interfaces/BUILD.gn
+++ b/mojo/services/media/common/interfaces/BUILD.gn
@@ -12,7 +12,6 @@
"media_state.mojom",
"media_transport.mojom",
"media_types.mojom",
- "rate_control.mojom",
"timelines.mojom",
]
}
diff --git a/mojo/services/media/common/interfaces/rate_control.mojom b/mojo/services/media/common/interfaces/rate_control.mojom
deleted file mode 100644
index bd7dd92..0000000
--- a/mojo/services/media/common/interfaces/rate_control.mojom
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2015 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.
-
-[DartPackage="mojo_services"]
-module mojo.media;
-
-// TimelineQuad
-// TODO(dalesat): Rename reference -> presentation.
-// TODO(dalesat): Rename target -> reference.
-//
-// A structure which holds the four numbers needed to define a linear
-// relationship between the points in two different timelines. The relationship
-// is expressed using 4 integers in order to facilitate compositions of multiple
-// transformations (A->B can be composed with B->C to produce the transformation
-// from A->C), and to minimize rounding and scaling errors when mapping points
-// between timelines which do not have an integer scaling relationship between
-// each other.
-//
-// These values are used to define the following functions which map from
-// points from the reference timeline to the target timeline, and back again.
-//
-// Let r be a point in the reference timeline.
-// Let t be a point in the target timeline timeline.
-// Let ref and tgt be abbreviations for reference and target in equations below.
-//
-// Given that r and t represent the same instant in time (in a single frame of
-// reference)
-//
-// t = f(r) = (((r - ref_offset) * tgt_delta) / ref_delta) + tgt_offset
-// r = F(t) = (((t - tgt_offset) * ref_delta) / tgt_delta) + ref_offset
-//
-// See also...
-// mojo/services/media/common/linear_transform.h
-//
-// no-format
-struct TimelineQuad {
- int64 reference_offset = 0;
- int64 target_offset = 0;
- uint32 reference_delta = 0;
- uint32 target_delta = 1;
-};
-// end-no-format
-
-// TimelineTransform
-// TODO(dalesat): Rename reference -> presentation.
-// TODO(dalesat): Rename target -> reference.
-//
-// A structure which holds both a timeline quad, and a pair of identifiers which
-// define the specific timelines which are the reference and target timelines.
-struct TimelineTransform {
- // TODO: These constants should probably defined by a central time management
- // service, not here.
- const uint32 kLocalTimeID = 0xFFFFFFFF;
- const uint32 kContextual = 0xFFFFFFFE;
-
- TimelineQuad quad;
- uint32 reference_timeline_id = kContextual;
- uint32 target_timeline_id = kLocalTimeID;
-};
-
-// RateControl
-//
-// An interface typically exposed by media renderers which allow producers of
-// media to specify how the presentation time stamps of the media queued to the
-// renderer relate to real time. Users may initialize the transformation with a
-// specific Quad, change the rate immediately in a first order contiguous
-// fashion, or schedule ranges in the rate at points in time on either the
-// reference or target timelines.
-interface RateControl {
- // Get the current quad which describes the transformation between the
- // reference and target timelines.
- GetCurrentTransform() => (TimelineTransform trans);
-
- // Immediately, explicitly set the quad which describes the mapping from
- // reference to target timeline. It is understood that this can cause
- // discontinuities and should only be used in situations which are already
- // fundamentally discontinuous (startup/seeking, for example)
- SetCurrentQuad(TimelineQuad quad);
-
- // Configure the target timeline ID. Note, the reference timeline ID will
- // always be contextual.
- SetTargetTimelineID(uint32 id);
-
- // Immediately change the rate of the existing transformation in a fashion
- // which is first order continuous with the current transformation.
- SetRate(uint32 reference_delta, uint32 target_delta);
-
- // Schedule a first order continuous rate change at the specified reference
- // time.
- SetRateAtReferenceTime(uint32 reference_delta,
- uint32 target_delta,
- int64 reference_time);
-
- // Schedule a first order continuous rate change at the specified target time.
- SetRateAtTargetTime(uint32 reference_delta,
- uint32 target_delta,
- int64 target_time);
-
- // Cancel any pending rate changes
- CancelPendingChanges();
-};
diff --git a/mojo/services/media/common/interfaces/timelines.mojom b/mojo/services/media/common/interfaces/timelines.mojom
index edee74d..39e4aef 100644
--- a/mojo/services/media/common/interfaces/timelines.mojom
+++ b/mojo/services/media/common/interfaces/timelines.mojom
@@ -7,6 +7,9 @@
// TODO(dalesat): Move out of media to somewhere more generic.
+// Used as a placefolder for unspecified time values.
+const int64 kUnspecifiedTime = 0x7fffffffffffffff;
+
// Represents the relationship between and subject timeline and a reference
// timeline.
//
@@ -37,8 +40,6 @@
// A push-mode consumer of timeline updates.
interface TimelineConsumer {
- const int64 kUnspecifiedTime = 0x7fffffffffffffff;
-
// Sets the timeline transform at the indicated effective time. Exactly one
// of the effective_*_time values must be kUnspecifiedTime.
// effective_subject_time can only be specified if the current subject_delta
diff --git a/mojo/services/media/control/interfaces/media_player.mojom b/mojo/services/media/control/interfaces/media_player.mojom
index b612c17..49f4aa4 100644
--- a/mojo/services/media/control/interfaces/media_player.mojom
+++ b/mojo/services/media/control/interfaces/media_player.mojom
@@ -7,7 +7,7 @@
import "mojo/services/media/common/interfaces/media_metadata.mojom";
import "mojo/services/media/common/interfaces/media_state.mojom";
-import "mojo/services/media/common/interfaces/rate_control.mojom";
+import "mojo/services/media/common/interfaces/timelines.mojom";
// Plays media.
interface MediaPlayer {
@@ -40,7 +40,7 @@
// Transform translating local time to presentation time. Reverse translation
// (presentation time to local time) is only valid when media is playing.
- TimelineTransform? timeline_transform;
+ mojo.TimelineTransform? timeline_transform;
// Describes the media.
MediaMetadata? metadata;
diff --git a/mojo/services/media/control/interfaces/media_sink.mojom b/mojo/services/media/control/interfaces/media_sink.mojom
index 45268cc..ac6c311 100644
--- a/mojo/services/media/control/interfaces/media_sink.mojom
+++ b/mojo/services/media/control/interfaces/media_sink.mojom
@@ -9,7 +9,7 @@
import "mojo/services/media/common/interfaces/media_state.mojom";
import "mojo/services/media/common/interfaces/media_transport.mojom";
import "mojo/services/media/common/interfaces/media_types.mojom";
-import "mojo/services/media/common/interfaces/rate_control.mojom";
+import "mojo/services/media/common/interfaces/timelines.mojom";
// TODO(dalesat): Define a media sink that multiplexes streams.
@@ -44,5 +44,5 @@
// Transform translating local time to presentation time. Reverse translation
// (presentation time to local time) is only valid when media is playing.
- TimelineTransform? timeline_transform;
+ mojo.TimelineTransform? timeline_transform;
};
diff --git a/mojo/services/media/core/interfaces/timeline_controller.mojom b/mojo/services/media/core/interfaces/timeline_controller.mojom
index 895b5d5..b18bea0 100644
--- a/mojo/services/media/core/interfaces/timeline_controller.mojom
+++ b/mojo/services/media/core/interfaces/timeline_controller.mojom
@@ -9,50 +9,13 @@
// Timing controller for a media graph.
interface MediaTimelineController {
- const int64 kUnspecifiedTime = 0x7fffffffffffffff;
- const uint64 kInitialStatus = 0;
-
// Associates a control site with the controller.
AddControlSite(MediaTimelineControlSite control_site);
- // Gets the status. To get the status immediately, call
- // GetStatus(kInitialStatus). To get updates thereafter, pass
- // the version sent in the previous callback.
- GetStatus(uint64 version_last_seen)
- => (uint64 version, MediaTimelineControllerStatus status);
-
- // Sets the timeline transform at the indicated effective time. At least one
- // of the effective_*_time values must be kUnspecifiedTime. If both are
- // kUnspecifiedTime, the requested change is implemented as soon as possible.
- // effective_subject_time can only be specified if the current subject_delta
- // isn’t zero. reference_delta may not be zero. subject_time may be
- // kUnspecifiedTime to indicate that the new transform subject_time should
- // be inferred from the effective time. The reference time for the new
- // transform (the reference time that will correspond to the specified or
- // inferred subject_time) is always inferred from the effective time. The
- // callback is called at the effective time or when a pending operation is
- // cancelled due to a subsequent call, in which case the 'completed' value is
- // false.
- SetTimelineTransform(
- int64 subject_time,
- uint32 subject_delta,
- uint32 reference_delta,
- int64 effective_subject_time,
- int64 effective_reference_time) => (bool completed);
-
// Gets a timeline control site interface for the controller.
GetControlSite(MediaTimelineControlSite& control_site);
};
-// Status returned by MediaTimelineController's GetStatus method.
-struct MediaTimelineControllerStatus {
- // Current timeline transform.
- mojo.TimelineTransform timeline_transform;
-
- // Whether end of stream was encountered.
- bool end_of_stream;
-};
-
// Media graph component controlled by a MediaTimelineController.
interface MediaTimelineControlSite {
const uint64 kInitialStatus = 0;
@@ -69,9 +32,9 @@
// Status returned by MediaTimelineControlSite's GetStatus method.
struct MediaTimelineControlSiteStatus {
- // Whether end of stream was encountered.
- bool end_of_stream;
+ // Current timeline transform.
+ mojo.TimelineTransform timeline_transform;
- // Whether the site is starving.
- bool starving;
+ // Indicates whether presentation has reached end-of-stream.
+ bool end_of_stream;
};
diff --git a/services/media/audio/audio_track_impl.cc b/services/media/audio/audio_track_impl.cc
index 7b9a8e0..87f3418 100644
--- a/services/media/audio/audio_track_impl.cc
+++ b/services/media/audio/audio_track_impl.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "mojo/services/media/common/cpp/linear_transform.h"
+#include "mojo/services/media/common/cpp/timeline.h"
#include "services/media/audio/audio_output_manager.h"
#include "services/media/audio/audio_server_impl.h"
#include "services/media/audio/audio_track_impl.h"
@@ -72,7 +73,7 @@
// for the service to destroy us. Run some DCHECK sanity checks and get out.
if (!binding_.is_bound()) {
DCHECK(!pipe_.IsInitialized());
- DCHECK(!rate_control_.is_bound());
+ DCHECK(!timeline_control_site_.is_bound());
DCHECK(!outputs_.size());
return;
}
@@ -84,7 +85,7 @@
// reset all of our internal state and close any other client connections in
// the process.
pipe_.Reset();
- rate_control_.Reset();
+ timeline_control_site_.Reset();
outputs_.clear();
DCHECK(owner_);
@@ -193,6 +194,8 @@
return;
}
+ frames_per_ns_ =
+ TimelineRate(cfg->frames_per_second, Timeline::ns_from_seconds(1));
// Figure out the rate we need to scale by in order to produce our fixed
// point timestamps.
@@ -262,10 +265,9 @@
owner_->GetOutputManager().SelectOutputsForTrack(strong_this);
}
-void AudioTrackImpl::GetRateControl(InterfaceRequest<RateControl> req) {
- if (!rate_control_.Bind(req.Pass())) {
- Shutdown();
- }
+void AudioTrackImpl::GetTimelineControlSite(
+ InterfaceRequest<MediaTimelineControlSite> req) {
+ timeline_control_site_.Bind(req.Pass());
}
void AudioTrackImpl::SetGain(float db_gain) {
@@ -306,6 +308,23 @@
}
}
+void AudioTrackImpl::SnapshotRateTrans(LinearTransform* out,
+ uint32_t* generation) {
+ TimelineFunction timeline_function;
+ timeline_control_site_.SnapshotCurrentFunction(
+ Timeline::local_now(), &timeline_function, generation);
+
+ // The control site works in ns units. We want the rate in frames per
+ // nanosecond, so we convert here.
+ TimelineRate rate_in_frames_per_ns =
+ timeline_function.rate() * frames_per_ns_;
+
+ *out = LinearTransform(timeline_function.reference_time(),
+ rate_in_frames_per_ns.subject_delta(),
+ rate_in_frames_per_ns.reference_delta(),
+ timeline_function.subject_time() * frames_per_ns_);
+}
+
void AudioTrackImpl::OnPacketReceived(AudioPipe::AudioPacketRefPtr packet) {
DCHECK(packet);
for (const auto& output : outputs_) {
diff --git a/services/media/audio/audio_track_impl.h b/services/media/audio/audio_track_impl.h
index f282849..71ec3e1 100644
--- a/services/media/audio/audio_track_impl.h
+++ b/services/media/audio/audio_track_impl.h
@@ -15,7 +15,7 @@
#include "mojo/services/media/common/cpp/linear_transform.h"
#include "services/media/audio/audio_pipe.h"
#include "services/media/audio/fwd_decls.h"
-#include "services/media/common/rate_control_base.h"
+#include "services/media/common/timeline_control_site.h"
namespace mojo {
namespace media {
@@ -41,9 +41,7 @@
// Accessors used by AudioOutputs during mixing to access parameters which are
// important for the mixing process.
- void SnapshotRateTrans(LinearTransform* out, uint32_t* generation = nullptr) {
- rate_control_.SnapshotCurrentTransform(out, generation);
- }
+ void SnapshotRateTrans(LinearTransform* out, uint32_t* generation = nullptr);
const LinearTransform::Ratio& FractionalFrameToMediaTimeRatio() const {
return frame_to_media_ratio_;
@@ -63,7 +61,8 @@
void Describe(const DescribeCallback& cbk) override;
void Configure(AudioTrackConfigurationPtr configuration,
InterfaceRequest<MediaConsumer> req) override;
- void GetRateControl(InterfaceRequest<RateControl> req) override;
+ void GetTimelineControlSite(InterfaceRequest<MediaTimelineControlSite> req)
+ override;
void SetGain(float db_gain) override;
// Methods called by our AudioPipe.
@@ -80,7 +79,8 @@
AudioServerImpl* owner_;
Binding<AudioTrack> binding_;
AudioPipe pipe_;
- RateControlBase rate_control_;
+ TimelineControlSite timeline_control_site_;
+ TimelineRate frames_per_ns_;
LinearTransform::Ratio frame_to_media_ratio_;
uint32_t bytes_per_frame_ = 1;
AudioMediaTypeDetailsPtr format_;
diff --git a/services/media/common/BUILD.gn b/services/media/common/BUILD.gn
index bc1e1b2..51880fa 100644
--- a/services/media/common/BUILD.gn
+++ b/services/media/common/BUILD.gn
@@ -10,13 +10,16 @@
sources = [
"media_pipe_base.cc",
"media_pipe_base.h",
- "rate_control_base.cc",
+ "mojo_publisher.h",
+ "timeline_control_site.cc",
+ "timeline_control_site.h",
]
deps = [
"//base",
"//mojo/services/media/common/cpp",
"//mojo/services/media/common/interfaces",
+ "//mojo/services/media/core/interfaces",
]
}
diff --git a/services/media/factory_service/mojo_publisher.h b/services/media/common/mojo_publisher.h
similarity index 91%
rename from services/media/factory_service/mojo_publisher.h
rename to services/media/common/mojo_publisher.h
index 0fb4e88..503ce61 100644
--- a/services/media/factory_service/mojo_publisher.h
+++ b/services/media/common/mojo_publisher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SERVICES_MEDIA_FRAMEWORK_MOJO_PUBLISHER_H_
-#define SERVICES_MEDIA_FRAMEWORK_MOJO_PUBLISHER_H_
+#ifndef SERVICES_MEDIA_COMMON_MOJO_PUBLISHER_H_
+#define SERVICES_MEDIA_COMMON_MOJO_PUBLISHER_H_
#include <functional>
#include <vector>
@@ -62,4 +62,4 @@
} // namespace media
} // namespace mojo
-#endif // SERVICES_MEDIA_FRAMEWORK_MOJO_MOJO_ALLOCATOR_H_
+#endif // SERVICES_MEDIA_COMMON_MOJO_PUBLISHER_H_
diff --git a/services/media/common/rate_control_base.cc b/services/media/common/rate_control_base.cc
deleted file mode 100644
index c72d265..0000000
--- a/services/media/common/rate_control_base.cc
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2015 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.
-
-#include "base/debug/stack_trace.h"
-#include "base/logging.h"
-#include "mojo/services/media/common/cpp/local_time.h"
-#include "services/media/common/rate_control_base.h"
-
-namespace mojo {
-namespace media {
-
-static inline int64_t LocalTimeNow() {
- return LocalClock::now().time_since_epoch().count();
-}
-
-RateControlBase::RateControlBase()
- : binding_(this)
- , current_transform_(0, 1) {
-}
-
-RateControlBase::~RateControlBase() {
- Reset();
-}
-
-bool RateControlBase::Bind(InterfaceRequest<RateControl> request) {
- Reset();
-
- binding_.Bind(request.Pass());
- binding_.set_connection_error_handler([this]() -> void {
- Reset();
- });
-
- return true;
-}
-
-void RateControlBase::SnapshotCurrentTransform(LinearTransform* out,
- uint32_t* generation) {
- DCHECK(out);
- base::AutoLock lock(transform_lock_);
- ApplyPendingChangesLocked(LocalTimeNow());
- *out = current_transform_;
- if (generation) {
- *generation = generation_;
- }
-}
-
-void RateControlBase::GetCurrentTransform(
- const GetCurrentTransformCallback& cbk) {
- TimelineTransformPtr ret(TimelineTransform::New());
- ret->quad = TimelineQuad::New();
-
- LinearTransform trans;
- SnapshotCurrentTransform(&trans);
- ret->quad->target_offset = trans.a_zero;
- ret->quad->reference_offset = trans.b_zero;
- ret->quad->target_delta = trans.scale.denominator;
- ret->quad->reference_delta = trans.scale.numerator;
- ret->reference_timeline_id = TimelineTransform::kContextual;
- ret->target_timeline_id = TimelineTransform::kLocalTimeID;
-
- cbk.Run(ret.Pass());
-}
-
-// TODO(johngro): implement or remove. Until we have the ability to query the
-// clock in the target timeline (or at least, transform local time to the target
-// timeline), we have no way to apply scheduled changes.
-void RateControlBase::SetTargetTimelineID(uint32_t id) {
- if (id != TimelineTransform::kLocalTimeID) {
- LOG(ERROR) << "Unsupported target timeline id ("
- << id << ") during SetTargetTimelineID";
- Reset();
- }
-}
-
-void RateControlBase::SetCurrentQuad(TimelineQuadPtr quad) {
- // A target delta of zero means that the transformation from the target
- // timeline to the media timeline is singular. This is not permitted, log an
- // error and close the connection if someone attempts to do this.
- if (!quad->target_delta) {
- OnIllegalRateChange(quad->reference_delta, quad->target_delta);
- return;
- } else {
- base::AutoLock lock(transform_lock_);
-
- reference_pending_changes_.clear();
- target_pending_changes_.clear();
-
- current_transform_.a_zero = quad->target_offset;
- current_transform_.b_zero = quad->reference_offset;
-
- if (quad->reference_delta) {
- current_transform_.scale =
- LinearTransform::Ratio(quad->reference_delta, quad->target_delta);
- } else {
- current_transform_.scale.numerator = 0;
- current_transform_.scale.denominator = 1;
- }
-
- AdvanceGenerationLocked();
- }
-}
-
-void RateControlBase::SetRate(uint32_t reference_delta, uint32_t target_delta) {
- // Only rate changes with a non-zero target_delta are permitted. See comment
- // in SetCurrentQuad.
- if (!target_delta) {
- OnIllegalRateChange(reference_delta, target_delta);
- return;
- } else {
- base::AutoLock lock(transform_lock_);
-
- // Make sure we are up to date.
- int64_t target_now = LocalTimeNow();
- ApplyPendingChangesLocked(target_now);
-
- DCHECK(current_transform_.scale.denominator);
- int64_t reference_now;
- if (!current_transform_.DoForwardTransform(target_now, &reference_now)) {
- // TODO(johngro): we cannot apply this transformation because of
- // overflow, so we are forced to skip it. Should we introduce a callback
- // to allow the user to know that their transformation was skipped?
- // Alternatively, should we log something about how the transformation was
- // skipped?
- return;
- }
-
- current_transform_.a_zero = target_now;
- current_transform_.b_zero = reference_now;
- current_transform_.scale.numerator = reference_delta;
- current_transform_.scale.denominator = target_delta;
-
- AdvanceGenerationLocked();
- }
-}
-
-void RateControlBase::SetRateAtReferenceTime(uint32_t reference_delta,
- uint32_t target_delta,
- int64_t reference_time) {
- // Only rate changes with a non-zero target_delta are permitted. See comment
- // in SetCurrentQuad.
- if (!target_delta) {
- OnIllegalRateChange(reference_delta, target_delta);
- return;
- } else {
- base::AutoLock lock(transform_lock_);
-
- // If the user tries to schedule a change which takes place before any
- // already scheduled change, ignore it.
- if (reference_pending_changes_.size() &&
- reference_pending_changes_.back().b_zero >= reference_time) {
- return;
- }
-
- reference_pending_changes_.emplace_back(0,
- reference_delta,
- target_delta,
- reference_time);
- }
-}
-
-void RateControlBase::SetRateAtTargetTime(uint32_t reference_delta,
- uint32_t target_delta,
- int64_t target_time) {
- // Only rate changes with a non-zero target_delta are permitted. See comment
- // in SetCurrentQuad.
- if (!target_delta) {
- OnIllegalRateChange(reference_delta, target_delta);
- return;
- } else {
- base::AutoLock lock(transform_lock_);
-
- // If the user tries to schedule a change which takes place before any
- // already scheduled change, ignore it.
- if (target_pending_changes_.size() &&
- target_pending_changes_.back().a_zero >= target_time) {
- return;
- }
-
- target_pending_changes_.emplace_back(target_time,
- reference_delta,
- target_delta,
- 0);
- }
-}
-
-void RateControlBase::CancelPendingChanges() {
- base::AutoLock lock(transform_lock_);
-
- reference_pending_changes_.clear();
- target_pending_changes_.clear();
-}
-
-void RateControlBase::ApplyPendingChangesLocked(int64_t target_now) {
- bool advance_generation = false;
-
- do {
- // Grab a pointer to the next pending target scheduled transform which is
- // not in the future, if any.
- int64_t target_age;
- const LinearTransform* target_trans = nullptr;
- if (target_pending_changes_.size() &&
- (target_now >= target_pending_changes_.front().a_zero)) {
- target_trans = &target_pending_changes_.front();
- target_age = target_now - target_trans->a_zero;
- }
-
- // Grab a pointer to the next pending reference scheduled transform which is
- // not in the future, if any.
- //
- // TODO(johngro): Optimize this. When we have pending reference scheduled
- // transformations, we don't have to compute this each and every time. We
- // could just keep the time of the next reference scheduled change
- // (expressed in target time) pre-computed, and only update it when the
- // current transformation actually changes.
- int64_t reference_age;
- int64_t next_reference_change_target_time;
- const LinearTransform* reference_trans = nullptr;
- if (reference_pending_changes_.size()) {
- if (current_transform_.DoReverseTransform(
- reference_pending_changes_.front().b_zero,
- &next_reference_change_target_time)) {
- if (target_now >= next_reference_change_target_time) {
- reference_age = target_now - next_reference_change_target_time;
- reference_trans = &reference_pending_changes_.front();
- }
- }
- }
-
- if (target_trans && (!reference_trans || (reference_age <= target_age))) {
- // If we have a target scheduled transform which should be applied, and we
- // either have no reference scheduled transform which should be applied,
- // or we have a reference scheduled transform which should be applied
- // after the pending target scheduled transform, go ahead and apply the
- // target transform.
- //
- // Note: if we cannot apply this transformation due to overflow, we have a
- // serious problem. For now, we just purge the scheduled transformation
- // and move on, but this is something which should never happen. We
- // should probably signal an error up to the user somehow.
- int64_t next_target_change_reference_time;
-
- if (current_transform_.DoForwardTransform(
- target_trans->a_zero,
- &next_target_change_reference_time)) {
- current_transform_.a_zero = target_trans->a_zero;
- current_transform_.b_zero = next_target_change_reference_time;
- current_transform_.scale.numerator = target_trans->scale.numerator;
- current_transform_.scale.denominator = target_trans->scale.denominator;
- DCHECK(current_transform_.scale.denominator);
- }
-
- advance_generation = true;
- target_pending_changes_.pop_front();
- } else if (reference_trans) {
- // We have a reference scheduled transformation which should be applied
- // before any pending target scheduled transformation. Do so now. No
- // need to compute the splice point for the function, we have already done
- // so when determining if we should apply this transformation or not.
- current_transform_.a_zero = next_reference_change_target_time;
- current_transform_.b_zero = reference_trans->a_zero;
- current_transform_.scale.numerator = reference_trans->scale.numerator;
- current_transform_.scale.denominator = reference_trans->scale.denominator;
- DCHECK(current_transform_.scale.denominator);
-
- advance_generation = true;
- reference_pending_changes_.pop_front();
- } else {
- // We have no transformations which need to be applied at the moment. We
- // are done for now.
- break;
- }
- } while (true);
-
- // If we have applied any changes, advance the transformation generation
- if (advance_generation) {
- AdvanceGenerationLocked();
- }
-}
-
-void RateControlBase::OnIllegalRateChange(uint32_t numerator,
- uint32_t denominator) {
- LOG(ERROR) << "Illegal rate change requested ("
- << numerator << "/" << denominator << ")";
- Reset();
-}
-
-void RateControlBase::Reset() {
- CancelPendingChanges();
- SetRate(0, 1);
-
- if (binding_.is_bound()) {
- binding_.set_connection_error_handler(mojo::Closure());
- binding_.Close();
- }
-}
-
-} // namespace media
-} // namespace mojo
diff --git a/services/media/common/rate_control_base.h b/services/media/common/rate_control_base.h
deleted file mode 100644
index 95d55fa..0000000
--- a/services/media/common/rate_control_base.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2015 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 SERVICES_MEDIA_COMMON_RATE_CONTROL_BASE_H_
-#define SERVICES_MEDIA_COMMON_RATE_CONTROL_BASE_H_
-
-#include <deque>
-
-#include "base/synchronization/lock.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/services/media/common/cpp/linear_transform.h"
-#include "mojo/services/media/common/interfaces/media_common.mojom.h"
-#include "mojo/services/media/common/interfaces/rate_control.mojom.h"
-
-namespace mojo {
-namespace media {
-
-class RateControlBase : public RateControl {
- public:
- // Default constructor and destructor
- RateControlBase();
- ~RateControlBase() override;
-
- bool Bind(InterfaceRequest<RateControl> request);
- bool is_bound() const { return binding_.is_bound(); }
-
- // Close any existing connections to clients, clear any pending rate changes
- // and set the clock rate to 0/1.
- void Reset();
-
- // TODO(johngro): snapshotting the current transform requires an evaluation of
- // all the pending timeline transformations. Currently, we allow users to
- // schedule an arbitrary number of pending transformations. This could cause
- // DoS hazards if a malicious (or just poorly written) application is
- // schedules a ton of transformations, and then something like the mixer
- // threads in the audio server is forced to collapse all of these
- // transformations in order to mix then next set of outbound audio frames.
- //
- // A simple way to avoid this would be to allow the user to have only one
- // pending transformation at any point in time.
- //
- // It would be nice to be able to simply return the transformation and use
- // Rvalue references in calling code to access the temporary snapshot, but
- // style does not permit us to use Rvalue references in such a way.
- //
- // Also; the way pending transformations get applied probably needs to be
- // re-worked. Currently, when we snapshot, we collapse any pending
- // transformations which should have occurred relative to LocalClock::now()
- // into the current transformation. For both video and audio, however, we are
- // always mixing/composing for a point in time in the near future, not for
- // right now. We really want to given the mixer compositor a view of what the
- // transformation is going to be at the mix/composition point, not what it is
- // now. Additionally, since audio process many frames at a time, we need to
- // give the audio mixer some knowledge of when we think the snapshotted
- // transformation is going to change next. The audio mixer wants to mix up to
- // that point, but not past it, and then fetch the new transformation before
- // proceeding.
- void SnapshotCurrentTransform(LinearTransform* out,
- uint32_t* generation = nullptr);
-
- // RateControl interface
- //
- void GetCurrentTransform(const GetCurrentTransformCallback& cbk) override;
- void SetTargetTimelineID(uint32_t id) override;
- void SetCurrentQuad(TimelineQuadPtr quad) override;
- void SetRate(uint32_t reference_delta, uint32_t target_delta) override;
- void SetRateAtReferenceTime(uint32_t reference_delta,
- uint32_t target_delta,
- int64_t reference_time) override;
- void SetRateAtTargetTime(uint32_t reference_delta,
- uint32_t target_delta,
- int64_t target_time) override;
- void CancelPendingChanges() override;
-
- protected:
- void ApplyPendingChangesLocked(int64_t target_now);
- void AdvanceGenerationLocked() {
- // bump the generation counter. Do not use the value 0.
- while (!(++generation_)) {}
- }
- void OnIllegalRateChange(uint32_t numerator, uint32_t denominator);
-
- Binding<RateControl> binding_;
- uint32_t target_timeline_id = TimelineTransform::kLocalTimeID;
-
- // Transformation state.
- //
- // Note: We use the LinearTransforms such that space A is the target timeline
- // and space B is the reference timeline. Applying this convention,
- // transforming from target to reference is the "forward" transformation and
- // is always defined. Transforming from reference to target is the "reverse"
- // transformation, and is only defined when we are not paused.
- // <pedantic>
- // OK; It is defined, but the equation has a singularity and the mapping is
- // not 1-to-1.
- // </pedantic>.
- base::Lock transform_lock_;
- LinearTransform current_transform_;
- std::deque<LinearTransform> reference_pending_changes_;
- std::deque<LinearTransform> target_pending_changes_;
- uint32_t generation_ = 1;
-};
-
-} // namespace media
-} // namespace mojo
-
-#endif // SERVICES_MEDIA_COMMON_RATE_CONTROL_BASE_H_
diff --git a/services/media/common/timeline_control_site.cc b/services/media/common/timeline_control_site.cc
new file mode 100644
index 0000000..26dc07f
--- /dev/null
+++ b/services/media/common/timeline_control_site.cc
@@ -0,0 +1,193 @@
+// 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.
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "mojo/services/media/common/cpp/timeline.h"
+#include "services/media/common/timeline_control_site.h"
+
+namespace mojo {
+namespace media {
+
+// For checking preconditions when handling mojo requests.
+// Checks the condition, and, if it's false, resets and calls return.
+#define RCHECK(condition) \
+ if (!(condition)) { \
+ LOG(ERROR) << "request precondition failed: " #condition "."; \
+ ResetUnsafe(); \
+ return; \
+ }
+
+TimelineControlSite::TimelineControlSite()
+ : control_site_binding_(this), consumer_binding_(this) {
+ task_runner_ = base::MessageLoop::current()->task_runner();
+ DCHECK(task_runner_);
+
+ base::AutoLock lock(lock_);
+ ClearPendingTimelineFunctionUnsafe(false);
+
+ status_publisher_.SetCallbackRunner(
+ [this](const GetStatusCallback& callback, uint64_t version) {
+ MediaTimelineControlSiteStatusPtr status;
+ {
+ base::AutoLock lock(lock_);
+ status = MediaTimelineControlSiteStatus::New();
+ status->timeline_transform =
+ TimelineTransform::From(current_timeline_function_);
+ status->end_of_stream = false; // TODO(dalesat): Provide this.
+ }
+ callback.Run(version, status.Pass());
+ });
+}
+
+TimelineControlSite::~TimelineControlSite() {}
+
+void TimelineControlSite::Bind(
+ InterfaceRequest<MediaTimelineControlSite> request) {
+ if (control_site_binding_.is_bound()) {
+ control_site_binding_.Close();
+ }
+
+ control_site_binding_.Bind(request.Pass());
+}
+
+void TimelineControlSite::Reset() {
+ if (control_site_binding_.is_bound()) {
+ control_site_binding_.Close();
+ }
+
+ if (consumer_binding_.is_bound()) {
+ consumer_binding_.Close();
+ }
+
+ {
+ base::AutoLock lock(lock_);
+ current_timeline_function_ = TimelineFunction();
+ ClearPendingTimelineFunctionUnsafe(false);
+ generation_ = 1;
+ }
+
+ status_publisher_.SendUpdates();
+}
+
+void TimelineControlSite::SnapshotCurrentFunction(int64_t reference_time,
+ TimelineFunction* out,
+ uint32_t* generation) {
+ DCHECK(out);
+ base::AutoLock lock(lock_);
+ ApplyPendingChangesUnsafe(reference_time);
+ *out = current_timeline_function_;
+ if (generation) {
+ *generation = generation_;
+ }
+}
+
+void TimelineControlSite::GetStatus(uint64_t version_last_seen,
+ const GetStatusCallback& callback) {
+ status_publisher_.Get(version_last_seen, callback);
+}
+
+void TimelineControlSite::GetTimelineConsumer(
+ InterfaceRequest<TimelineConsumer> timeline_consumer) {
+ if (consumer_binding_.is_bound()) {
+ consumer_binding_.Close();
+ }
+
+ consumer_binding_.Bind(timeline_consumer.Pass());
+}
+
+void TimelineControlSite::SetTimelineTransform(
+ int64_t subject_time,
+ uint32_t reference_delta,
+ uint32_t subject_delta,
+ int64_t effective_reference_time,
+ int64_t effective_subject_time,
+ const SetTimelineTransformCallback& callback) {
+ base::AutoLock lock(lock_);
+
+ // At most one of the effective times must be specified.
+ RCHECK(effective_reference_time == kUnspecifiedTime ||
+ effective_subject_time == kUnspecifiedTime);
+ // effective_subject_time can only be used if we're progressing already.
+ RCHECK(effective_subject_time == kUnspecifiedTime ||
+ current_timeline_function_.subject_delta() != 0);
+ RCHECK(reference_delta != 0);
+
+ if (effective_subject_time != kUnspecifiedTime) {
+ // Infer effective_reference_time from effective_subject_time.
+ effective_reference_time =
+ current_timeline_function_.ApplyInverse(effective_subject_time);
+
+ if (subject_time == kUnspecifiedTime) {
+ // Infer subject_time from effective_subject_time.
+ subject_time = effective_subject_time;
+ }
+ } else {
+ if (effective_reference_time == kUnspecifiedTime) {
+ // Neither effective time was specified. Effective time is now.
+ effective_reference_time = Timeline::local_now();
+ }
+
+ if (subject_time == kUnspecifiedTime) {
+ // Infer subject_time from effective_reference_time.
+ subject_time = current_timeline_function_(effective_reference_time);
+ }
+ }
+
+ // Eject any previous pending change.
+ ClearPendingTimelineFunctionUnsafe(false);
+
+ // Queue up the new pending change.
+ pending_timeline_function_ = TimelineFunction(
+ effective_reference_time, subject_time, reference_delta, subject_delta);
+
+ set_timeline_transform_callback_ = callback;
+}
+
+void TimelineControlSite::ApplyPendingChangesUnsafe(int64_t reference_time) {
+ lock_.AssertAcquired();
+
+ if (!TimelineFunctionPendingUnsafe() ||
+ pending_timeline_function_.reference_time() > reference_time) {
+ return;
+ }
+
+ current_timeline_function_ = pending_timeline_function_;
+ ClearPendingTimelineFunctionUnsafe(true);
+
+ ++generation_;
+
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&MojoPublisher<GetStatusCallback>::SendUpdates,
+ base::Unretained(&status_publisher_)));
+}
+
+void TimelineControlSite::ClearPendingTimelineFunctionUnsafe(bool completed) {
+ lock_.AssertAcquired();
+
+ pending_timeline_function_ =
+ TimelineFunction(kUnspecifiedTime, kUnspecifiedTime, 1, 0);
+ if (!set_timeline_transform_callback_.is_null()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&TimelineControlSite::RunCallback,
+ set_timeline_transform_callback_, completed));
+ set_timeline_transform_callback_.reset();
+ }
+}
+
+void TimelineControlSite::ResetUnsafe() {
+ lock_.AssertAcquired();
+ task_runner_->PostTask(FROM_HERE, base::Bind(&TimelineControlSite::Reset,
+ base::Unretained(this)));
+}
+
+// static
+void TimelineControlSite::RunCallback(SetTimelineTransformCallback callback,
+ bool completed) {
+ callback.Run(completed);
+}
+
+} // namespace media
+} // namespace mojo
diff --git a/services/media/common/timeline_control_site.h b/services/media/common/timeline_control_site.h
new file mode 100644
index 0000000..4b2506f
--- /dev/null
+++ b/services/media/common/timeline_control_site.h
@@ -0,0 +1,94 @@
+// 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 MOJO_SERVICES_MEDIA_COMMON_TIMELINE_CONTROL_SITE_IMPL_H_
+#define MOJO_SERVICES_MEDIA_COMMON_TIMELINE_CONTROL_SITE_IMPL_H_
+
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/services/media/common/cpp/timeline_function.h"
+#include "mojo/services/media/core/interfaces/timeline_controller.mojom.h"
+#include "services/media/common/mojo_publisher.h"
+
+namespace mojo {
+namespace media {
+
+// MediaTimelineControlSite implementation.
+class TimelineControlSite : public MediaTimelineControlSite,
+ public TimelineConsumer {
+ public:
+ TimelineControlSite();
+
+ ~TimelineControlSite() override;
+
+ // Binds to the control site. If a binding exists already, it is closed.
+ void Bind(InterfaceRequest<MediaTimelineControlSite> request);
+
+ // Determines whether the control site is currently bound.
+ bool is_bound() { return control_site_binding_.is_bound(); }
+
+ // Unbinds from clients and resets to initial state.
+ void Reset();
+
+ // Get the TimelineFunction for the reference_time (which should be 'now',
+ // approximately).
+ void SnapshotCurrentFunction(int64_t reference_time,
+ TimelineFunction* out,
+ uint32_t* generation = nullptr);
+
+ // MediaTimelineControlSite implementation.
+ void GetStatus(uint64_t version_last_seen,
+ const GetStatusCallback& callback) override;
+
+ void GetTimelineConsumer(
+ InterfaceRequest<TimelineConsumer> timeline_consumer) override;
+
+ // TimelineConsumer implementation.
+ void SetTimelineTransform(
+ int64_t subject_time,
+ uint32_t reference_delta,
+ uint32_t subject_delta,
+ int64_t effective_reference_time,
+ int64_t effective_subject_time,
+ const SetTimelineTransformCallback& callback) override;
+
+ private:
+ // Applies pending_timeline_function_ if it's time to do so based on the
+ // given reference time.
+ void ApplyPendingChangesUnsafe(int64_t reference_time);
+
+ // Clears the pending timeline function and calls its associated callback
+ // with the indicated completed status.
+ void ClearPendingTimelineFunctionUnsafe(bool completed);
+
+ // Determines if an unrealized timeline function is currently pending.
+ bool TimelineFunctionPendingUnsafe() {
+ return pending_timeline_function_.reference_time() != kUnspecifiedTime;
+ }
+
+ // Unbinds from clients and resets to initial state.
+ void ResetUnsafe();
+
+ static void RunCallback(SetTimelineTransformCallback callback,
+ bool completed);
+
+ Binding<MediaTimelineControlSite> control_site_binding_;
+ Binding<TimelineConsumer> consumer_binding_;
+ MojoPublisher<GetStatusCallback> status_publisher_;
+
+ base::Lock lock_;
+ // BEGIN fields synchronized using lock_.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ TimelineFunction current_timeline_function_;
+ TimelineFunction pending_timeline_function_;
+ SetTimelineTransformCallback set_timeline_transform_callback_;
+ uint32_t generation_ = 1;
+ // END fields synchronized using lock_.
+};
+
+} // namespace media
+} // namespace mojo
+
+#endif // MOJO_SERVICES_MEDIA_COMMON_TIMELINE_CONTROL_SITE_IMPL_H_
diff --git a/services/media/factory_service/BUILD.gn b/services/media/factory_service/BUILD.gn
index 21a1e4b..12f60e1 100644
--- a/services/media/factory_service/BUILD.gn
+++ b/services/media/factory_service/BUILD.gn
@@ -28,7 +28,6 @@
"media_sink_impl.h",
"media_source_impl.cc",
"media_source_impl.h",
- "mojo_publisher.h",
"network_reader_impl.cc",
"network_reader_impl.h",
]
@@ -45,6 +44,7 @@
"//mojo/services/media/control/interfaces",
"//mojo/services/media/core/interfaces",
"//mojo/services/network/interfaces",
+ "//services/media/common",
"//services/media/framework",
"//services/media/framework_create",
"//services/media/framework_ffmpeg",
diff --git a/services/media/factory_service/audio_track_controller.cc b/services/media/factory_service/audio_track_controller.cc
index e36e04b..3b85597 100644
--- a/services/media/factory_service/audio_track_controller.cc
+++ b/services/media/factory_service/audio_track_controller.cc
@@ -45,10 +45,10 @@
MediaConsumerPtr consumer;
audio_track_->Configure(config.Pass(), GetProxy(&consumer));
- RateControlPtr rate_control;
- audio_track_->GetRateControl(GetProxy(&rate_control));
+ MediaTimelineControlSitePtr timeline_control_site;
+ audio_track_->GetTimelineControlSite(GetProxy(&timeline_control_site));
- callback(consumer.Pass(), rate_control.Pass());
+ callback(consumer.Pass(), timeline_control_site.Pass());
}
} // namespace media
diff --git a/services/media/factory_service/audio_track_controller.h b/services/media/factory_service/audio_track_controller.h
index 9e15485..6a60dc9 100644
--- a/services/media/factory_service/audio_track_controller.h
+++ b/services/media/factory_service/audio_track_controller.h
@@ -19,7 +19,7 @@
using GetSupportedMediaTypesCallback = std::function<void(
std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>>)>;
using ConfigureCallback =
- std::function<void(MediaConsumerPtr, RateControlPtr)>;
+ std::function<void(MediaConsumerPtr, MediaTimelineControlSitePtr)>;
AudioTrackController(const String& url, ApplicationImpl* app);
diff --git a/services/media/factory_service/media_demux_impl.h b/services/media/factory_service/media_demux_impl.h
index 0be2435..43d96bf 100644
--- a/services/media/factory_service/media_demux_impl.h
+++ b/services/media/factory_service/media_demux_impl.h
@@ -13,8 +13,8 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/media/core/interfaces/media_demux.mojom.h"
#include "mojo/services/media/core/interfaces/seeking_reader.mojom.h"
+#include "services/media/common/mojo_publisher.h"
#include "services/media/factory_service/factory_service.h"
-#include "services/media/factory_service/mojo_publisher.h"
#include "services/media/framework/graph.h"
#include "services/media/framework/parts/demux.h"
#include "services/media/framework/util/incident.h"
diff --git a/services/media/factory_service/media_player_impl.h b/services/media/factory_service/media_player_impl.h
index 33a7595..0a09d9c 100644
--- a/services/media/factory_service/media_player_impl.h
+++ b/services/media/factory_service/media_player_impl.h
@@ -13,8 +13,8 @@
#include "mojo/services/media/common/interfaces/media_transport.mojom.h"
#include "mojo/services/media/control/interfaces/media_factory.mojom.h"
#include "mojo/services/media/core/interfaces/seeking_reader.mojom.h"
+#include "services/media/common/mojo_publisher.h"
#include "services/media/factory_service/factory_service.h"
-#include "services/media/factory_service/mojo_publisher.h"
namespace mojo {
namespace media {
diff --git a/services/media/factory_service/media_sink_impl.cc b/services/media/factory_service/media_sink_impl.cc
index da4b7ef..1fec5bd 100644
--- a/services/media/factory_service/media_sink_impl.cc
+++ b/services/media/factory_service/media_sink_impl.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "base/logging.h"
-#include "mojo/services/media/common/cpp/linear_transform.h"
-#include "mojo/services/media/common/cpp/local_time.h"
+#include "mojo/services/media/common/cpp/timeline.h"
+#include "mojo/services/media/common/cpp/timeline_function.h"
#include "services/media/factory_service/media_sink_impl.h"
#include "services/media/framework/util/conversion_pipeline_builder.h"
#include "services/media/framework_mojo/mojo_type_conversions.h"
@@ -32,15 +32,15 @@
DCHECK(destination_url);
DCHECK(media_type);
- status_publisher_.SetCallbackRunner(
- [this](const GetStatusCallback& callback, uint64_t version) {
- MediaSinkStatusPtr status = MediaSinkStatus::New();
- status->state = (producer_state_ == MediaState::PAUSED && rate_ != 0.0)
- ? MediaState::PLAYING
- : producer_state_;
- status->timeline_transform = status_transform_.Clone();
- callback.Run(version, status.Pass());
- });
+ status_publisher_.SetCallbackRunner([this](const GetStatusCallback& callback,
+ uint64_t version) {
+ MediaSinkStatusPtr status = MediaSinkStatus::New();
+ status->state = (producer_state_ == MediaState::PAUSED && rate_ != 0.0)
+ ? MediaState::PLAYING
+ : producer_state_;
+ status->timeline_transform = TimelineTransform::From(timeline_function_);
+ callback.Run(version, status.Pass());
+ });
PartRef consumer_ref = graph_.Add(consumer_);
PartRef producer_ref = graph_.Add(producer_);
@@ -112,7 +112,10 @@
graph_.ConnectOutputToPart(out, producer_ref);
if (producer_stream_type->medium() == StreamType::Medium::kAudio) {
- frames_per_second_ = producer_stream_type->audio()->frames_per_second();
+ frames_per_ns_ =
+ TimelineRate(producer_stream_type->audio()->frames_per_second(),
+ Timeline::ns_from_seconds(1));
+
} else {
// Unsupported producer stream type.
LOG(ERROR) << "unsupported producer stream type";
@@ -121,10 +124,12 @@
controller_->Configure(
std::move(producer_stream_type),
- [this](MediaConsumerPtr consumer, RateControlPtr rate_control) {
+ [this](MediaConsumerPtr consumer,
+ MediaTimelineControlSitePtr timeline_control_site) {
DCHECK(consumer);
- DCHECK(rate_control);
- rate_control_ = rate_control.Pass();
+ DCHECK(timeline_control_site);
+ timeline_control_site->GetTimelineConsumer(
+ GetProxy(&timeline_consumer_));
producer_->Connect(consumer.Pass(), [this]() {
graph_.Prepare();
ready_.Occur();
@@ -160,99 +165,46 @@
return;
}
- if (!rate_control_) {
+ if (!timeline_consumer_) {
rate_ = target_rate_;
status_publisher_.SendUpdates();
return;
}
- // Desired rate in frames per second.
- LinearTransform::Ratio rate_frames_per_second(
- static_cast<uint32_t>(frames_per_second_ * target_rate_), 1);
+ // TODO(dalesat): start_local_time and start_presentation_time should be
+ // supplied via the mojo interface. For now, start_local_time is hard-coded
+ // to be 30ms in the future, and start_presentation_time is grabbed from the
+ // first primed packet or is calculated from start_local_time based on the
+ // previous timeline function.
- // Local time rate in seconds_per_tick.
- LinearTransform::Ratio local_seconds_per_tick(LocalDuration::period::num,
- LocalDuration::period::den);
-
- // Desired rate in frames per local tick.
- LinearTransform::Ratio rate_frames_per_tick;
- bool success = LinearTransform::Ratio::Compose(
- local_seconds_per_tick, rate_frames_per_second, &rate_frames_per_tick);
- DCHECK(success)
- << "LinearTransform::Ratio::Compose reports loss of precision";
-
- // TODO(dalesat): start_local_time should be supplied via the mojo interface.
- // For now, it's hard-coded to be 30ms in the future.
// The local time when we want the rate to change.
- int64_t start_local_time =
- (LocalClock::now().time_since_epoch() + std::chrono::milliseconds(30))
- .count();
+ int64_t start_local_time = Timeline::local_now() + Timeline::ns_from_ms(30);
// The media time corresponding to start_local_time.
- int64_t start_media_time;
+ int64_t start_presentation_time;
if (flushed_ && producer_->GetFirstPtsSinceFlush() != Packet::kUnknownPts) {
// We're getting started initially or after a flush/prime, so the media
// time corresponding to start_local_time should be the PTS of
- // the first packet.
- start_media_time = producer_->GetFirstPtsSinceFlush();
+ // the first packet converted to ns (rather than frame) units.
+ start_presentation_time =
+ producer_->GetFirstPtsSinceFlush() / frames_per_ns_;
} else {
// We're resuming, so the media time corresponding to start_local_time can
// be calculated using the existing transform.
- success =
- transform_.DoForwardTransform(start_local_time, &start_media_time);
- DCHECK(success)
- << "LinearTransform::DoForwardTransform reports loss of precision";
+ start_presentation_time = timeline_function_(start_local_time);
}
flushed_ = false;
// Update the transform.
- transform_ =
- LinearTransform(start_local_time, rate_frames_per_tick, start_media_time);
+ timeline_function_ = TimelineFunction(
+ start_local_time, start_presentation_time, TimelineRate(target_rate_));
// Set the rate.
- TimelineQuadPtr rate_quad = TimelineQuad::New();
- rate_quad->reference_offset = start_media_time;
- rate_quad->target_offset = start_local_time;
- rate_quad->reference_delta = rate_frames_per_tick.numerator;
- rate_quad->target_delta = rate_frames_per_tick.denominator;
-
- rate_control_->SetCurrentQuad(rate_quad.Pass());
-
- // Get the frame rate in frames per local tick.
- LinearTransform::Ratio frame_rate_frames_per_second(frames_per_second_, 1);
- LinearTransform::Ratio frame_rate_frames_per_tick;
- success = LinearTransform::Ratio::Compose(local_seconds_per_tick,
- frame_rate_frames_per_second,
- &frame_rate_frames_per_tick);
- DCHECK(success)
- << "LinearTransform::Ratio::Compose reports loss of precision";
-
- // Create a LinearTransform to translate from presentation units to
- // local duration units.
- LinearTransform local_to_presentation(0, frame_rate_frames_per_tick, 0);
-
- status_transform_ = TimelineTransform::New();
- status_transform_->quad = TimelineQuad::New();
-
- // Translate the current transform quad so the presentation time units
- // are the same as the local time units.
- success = local_to_presentation.DoReverseTransform(
- start_media_time, &status_transform_->quad->reference_offset);
- DCHECK(success)
- << "LinearTransform::DoReverseTransform reports loss of precision";
- status_transform_->quad->target_offset = start_local_time;
- int64_t presentation_delta;
- success = local_to_presentation.DoReverseTransform(
- static_cast<int64_t>(rate_frames_per_tick.numerator),
- &presentation_delta);
- DCHECK(success)
- << "LinearTransform::DoReverseTransform reports loss of precision";
- status_transform_->quad->reference_delta =
- static_cast<uint32_t>(presentation_delta);
- status_transform_->quad->target_delta = rate_frames_per_tick.denominator;
- LinearTransform::Ratio::Reduce(&status_transform_->quad->reference_delta,
- &status_transform_->quad->target_delta);
+ timeline_consumer_->SetTimelineTransform(
+ timeline_function_.subject_time(), timeline_function_.reference_delta(),
+ timeline_function_.subject_delta(), timeline_function_.reference_time(),
+ kUnspecifiedTime, [](bool completed) {});
rate_ = target_rate_;
status_publisher_.SendUpdates();
diff --git a/services/media/factory_service/media_sink_impl.h b/services/media/factory_service/media_sink_impl.h
index 17db63a..f323f62 100644
--- a/services/media/factory_service/media_sink_impl.h
+++ b/services/media/factory_service/media_sink_impl.h
@@ -9,11 +9,11 @@
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/services/media/common/cpp/linear_transform.h"
+#include "mojo/services/media/common/cpp/timeline_function.h"
#include "mojo/services/media/control/interfaces/media_sink.mojom.h"
+#include "services/media/common/mojo_publisher.h"
#include "services/media/factory_service/audio_track_controller.h"
#include "services/media/factory_service/factory_service.h"
-#include "services/media/factory_service/mojo_publisher.h"
#include "services/media/framework/graph.h"
#include "services/media/framework/parts/decoder.h"
#include "services/media/framework/util/incident.h"
@@ -61,13 +61,12 @@
std::shared_ptr<MojoConsumer> consumer_;
std::shared_ptr<MojoProducer> producer_;
std::unique_ptr<AudioTrackController> controller_;
- RateControlPtr rate_control_;
+ TimelineConsumerPtr timeline_consumer_;
float rate_ = 0.0f;
float target_rate_ = 0.0f;
MediaState producer_state_ = MediaState::UNPREPARED;
- LinearTransform transform_ = LinearTransform(0, 0, 1, 0);
- TimelineTransformPtr status_transform_;
- uint32_t frames_per_second_ = 0u;
+ TimelineFunction timeline_function_;
+ TimelineRate frames_per_ns_;
bool flushed_ = true;
MojoPublisher<GetStatusCallback> status_publisher_;
};
diff --git a/services/media/factory_service/media_source_impl.h b/services/media/factory_service/media_source_impl.h
index 5fdd3ee..d056aa4 100644
--- a/services/media/factory_service/media_source_impl.h
+++ b/services/media/factory_service/media_source_impl.h
@@ -11,8 +11,8 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/media/control/interfaces/media_source.mojom.h"
#include "mojo/services/media/core/interfaces/seeking_reader.mojom.h"
+#include "services/media/common/mojo_publisher.h"
#include "services/media/factory_service/factory_service.h"
-#include "services/media/factory_service/mojo_publisher.h"
#include "services/media/framework/graph.h"
#include "services/media/framework/parts/decoder.h"
#include "services/media/framework/parts/demux.h"
diff --git a/services/media/framework_mojo/mojo_formatting.cc b/services/media/framework_mojo/mojo_formatting.cc
index 3afefac..7dfbc86 100644
--- a/services/media/framework_mojo/mojo_formatting.cc
+++ b/services/media/framework_mojo/mojo_formatting.cc
@@ -259,23 +259,6 @@
return os << outdent;
}
-std::ostream& operator<<(std::ostream& os, const TimelineQuadPtr& value) {
- if (!value) {
- return os << "<nullptr>" << std::endl;
- } else {
- os << std::endl;
- }
-
- os << indent;
- os << begl << "int64 reference_offset: " << value->reference_offset
- << std::endl;
- os << begl << "int64 target_offset: " << value->target_offset << std::endl;
- os << begl << "int32 reference_delta: " << value->reference_delta
- << std::endl;
- os << begl << "uint32 target_delta: " << value->target_delta << std::endl;
- return os << outdent;
-}
-
std::ostream& operator<<(std::ostream& os, const TimelineTransformPtr& value) {
if (!value) {
return os << "<nullptr>" << std::endl;
@@ -284,11 +267,12 @@
}
os << indent;
- os << begl << "TimelineQuad quad: " << value->quad;
- os << begl << "uint32 reference_timeline_id: " << value->reference_timeline_id
+ os << begl << "int64 reference_time: " << value->reference_time
<< std::endl;
- os << begl << "uint32 target_timeline_id: " << value->target_timeline_id
+ os << begl << "int64 subject_time: " << value->subject_time << std::endl;
+ os << begl << "uint32 reference_delta: " << value->reference_delta
<< std::endl;
+ os << begl << "uint32 subject_delta: " << value->subject_delta << std::endl;
return os << outdent;
}
diff --git a/services/media/framework_mojo/mojo_formatting.h b/services/media/framework_mojo/mojo_formatting.h
index 507cd5c..020d47e 100644
--- a/services/media/framework_mojo/mojo_formatting.h
+++ b/services/media/framework_mojo/mojo_formatting.h
@@ -8,7 +8,7 @@
#include "mojo/services/media/common/interfaces/media_common.mojom.h"
#include "mojo/services/media/common/interfaces/media_transport.mojom.h"
#include "mojo/services/media/common/interfaces/media_types.mojom.h"
-#include "mojo/services/media/common/interfaces/rate_control.mojom.h"
+#include "mojo/services/media/common/interfaces/timelines.mojom.h"
#include "mojo/services/media/control/interfaces/media_source.mojom.h"
#include "mojo/services/network/interfaces/network_service.mojom.h"
#include "services/media/framework/util/formatting.h"
@@ -50,7 +50,6 @@
const SubpictureMediaTypeSetDetailsPtr& value);
std::ostream& operator<<(std::ostream& os,
const MediaSourceStreamDescriptorPtr& value);
-std::ostream& operator<<(std::ostream& os, const TimelineQuadPtr& value);
std::ostream& operator<<(std::ostream& os, const TimelineTransformPtr& value);
std::ostream& operator<<(std::ostream& os, const HttpHeaderPtr& value);