blob: 67dbc6ffea5149606c4ab62dc950c6dd6ba3ab2e [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.media;
//
// AudioOuts can be in one of two states at any point in time, either
// the configurable state or the operational state. An AudioOut is considered
// to be operational any time it has packets queued and waiting to be
// rendered. configurable state. When an AudioOut has entered the operational
// state of its life, any attempt call a config method in the interface is
// considered to be illegal and will result in termination of the interface's
// connection to the audio server.
//
// If an AudioOut needs to be reconfigured, it is best practice to
// always 'DiscardAllPackets' on the AudioOut before starting to reconfigure it.
//
// Ordinal range: 0x0600-0x6ff
interface AudioOut {
/////////////////////////////////////////////////////////////////////////////
// AudioOut methods
// These methods will remain in AudioOut.
// Sets the type of the stream to be delivered by the client. Using this
// method implies that the stream encoding is AUDIO_ENCODING_LPCM.
0x0601: SetPcmStreamType(AudioStreamType type);
// Sets the type of the stream to be delivered by the client. This method
// is used for compressed pass-through. The media_specific field must of
// type audio.
// NOTE: Not currently implemented.
0x0602: SetStreamType(StreamType type);
// Sets the units used by the presentation timeline. By default, these
// units are nanoseconds (1e9/1).
0x0603: SetPtsUnits(uint32 tick_per_second_numerator,
uint32 tick_per_second_denominator);
// Sets the maximum distance (in frames) between an explicit PTS (provided by
// the user) and the expected PTS (determined using interpolation) which may
// occur in an audio packet stream, and still be treated as 'continuous' by
// the AudioOut.
//
// Defaults to RoundUp((AudioFPS/PTSTicksPerSec) / 2.0) / AudioFPS
// The majority of uses should not need to change this value from its
// default.
//
// Example:
// A user is playing back 48KHz audio from a container, which also contains
// video and needs to be synchronized with the audio. The timestamps are
// provided explicitly per packet by the container, and expressed in mSec
// units. This means that a single tick of the media timeline (1 mSec)
// represents exactly 48 frames of audio. The application in this scenario
// delivers packets of audio to the AudioOut, each with exactly 470 frames of
// audio, and each with an explicit timestamp set to the best possible
// representation of the presentation time (given this media clock's
// resolution). So, starting from zero, the timestamps would be..
//
// [ 0, 10, 20, 29, 39, 49, 59, 69, 78, 88, ... ]
//
// In this example, attempting to use the presentation time to compute the
// starting frame number of the audio in the packet would be wrong the
// majority of the time. The first timestamp is correct (by definition), but
// it will be 24 packets before the timestamps and frame numbers come back
// into alignment (the 24th packet would start with the 11280th audio frame
// and have a PTS of exactly 235).
//
// One way to fix this situation is to set the PTS continuity threshold
// (henceforth, CT) for the stream to be equal to 1/2 of the time taken by the
// number of frames contained within a single tick of the media clock, rounded
// up. In this scenario, that would be 24.0 frames of audio, or 500 uSec.
// Any packets whose expected PTS was within +/-CT frames of the explicitly
// provided PTS would be considered to be a continuation of the previous frame
// of audio.
//
// Other possible uses:
// Users who are scheduling audio explicitly relative to a clock which has not
// been configured as the reference clock can use this value to control the
// maximum acceptable synchronization error before a discontinuity is
// introduced. Eg, if a user is scheduling audio based on a recovered common
// media clock, and has not published that clock as the reference clock, and
// they set the CT to 20mSec, then up to 20mSec of drift error can accumulate
// before the AudioOut deliberately inserts a presentation discontinuity
// to account for the error.
//
// Users whose need to deal with a container where their timestamps may be
// even less correct than +/- 1/2 of a PTS tick may set this value to
// something larger. This should be the maximum level of inaccuracy present
// in the container timestamps, if known. Failing that, it could be set to
// the maximum tolerable level of drift error before the timestamps are
// explicitly obeyed. Finally, a user could set this number to a very large
// value (86400.0 seconds, for example) to effectively cause *all* timestamps
// to be ignored after the first, and have all the audio be treated as
// continuous with any previously delivered packets. Conversely, users who
// wish to *always* explicitly schedule their audio exactly may specify a CT
// of 0.
//
0x0604: SetPtsContinuityThreshold(float32 threshold_seconds);
// Set the reference clock used to control playback rate and as the reference
// for scheduled clock transformations.
//
// TODO(mpuryear) : refine this data type when we have a solid definition of
// what a clock handle is/looks like. Also, should we allow the user to lock
// their rate to CLOCK_MONO instead of following the default (perhaps dynamic)
// system rate?
0x0605: SetReferenceClock(handle reference_clock);
// Immediately put the AudioOut into the playing state, and then report the
// relationship between the media and reference timelines which was
// established (if requested).
//
// The act of placing a AudioOut into the playback state establishes a
// relationship between the user-defined media (or presentation) timeline, and
// the real-world reference timeline. In order to do so, two timestamps (one
// on the media timeline, one on the reference timeline) must be established
// as being related. IOW - The audio frame at timestamp X will be presented
// at reference time Y. Users may explicitly provide both timestamps, one of
// the timestamps, or neither of the timestamps, depending on their use case.
// A timestamp may be omitted by supplying the special value kNoTimestamp.
// In the case that a timestamp is omitted, the AudioOut automatically
// deduce the timestamp to use based on the following rules.
//
// Reference Time
// If the reference time is omitted, the AudioOut will select a
// reference time to begin presentation which is currently safe based on the
// minimum lead times for each of the audio outputs the AudioOut is currently
// bound to. For example, if the AudioOut was bound to an internal audio
// output which required a minimum of 3 mSec of lead time, and an HDMI output
// which required a minimum of 75 mSec of lead time, the AudioOut might
// automatically schedule presentation to begin 80 mSec from now.
//
// Media Time
// If the media time is omitted, the audio AudioOut will select one of two
// value to use. If the AudioOut is resuming from the paused state, and
// packets have not been discarded since being paused, then the AudioOut will
// use the time, in the media timeline, at which the presentation became
// paused as the media_time value. If the AudioOut is being placed in the
// playing state for the first time following either startup or a 'discard
// packets' operation, the media_time selected will be the PTS of the first
// payload in the pending queue. If the pending queue is empty, a value of
// zero will be used for the media_time.
//
// Return Value
// When requested, the AudioOut will return the reference_time and media_time
// which were selected and used (whether they were explicitly specified or
// not) in the return value of the play call.
//
// Examples
// A user has queued some audio using SendPacket and simply wishes them to
// start playing as soon as possible. The user may simply call Play(), with
// no explicit timestamps provided.
//
// A user has queued some audio using SendPacket, and wishes to start playback
// at reference time X, in sync with another stream (either audio, or video),
// either initially or after discarding packets. The user would call Play(X).
//
// A user has queued some audio using SendPacket. The first of these packets
// has a PTS of zero, and the user wishes to begin playback as soon as
// possible, but wishes to skip the first X media timeline units worth of
// audio. The user would call Play(kNoTimestamp, X).
//
// A user has queued some audio using SendPacket and is attempting to present
// media in synch with another player in a different device. The coordinator
// of the group of distributed players sends an explicit message to each
// player telling them to begin presentation of media_time X at the group's
// shared reference time Y. The user would call Play(Y, X).
//
// TODO(mpuryear): Define behavior in the case that a user calls Play while the
// system is already in the playing state. We should probably do nothing but
// provide a valid correspondence pair in response unless both the reference
// and the media time are provided, in which case we should introduce a
// discontinuity.
//
// TODO(mpuryear): Collapse these if we ever have optional retvals in FIDL
0x0606: Play(int64 reference_time, int64 media_time) ->
(int64 reference_time, int64 media_time);
0x0607: PlayNoReply(int64 reference_time, int64 media_time);
// Immediately put the AudioOut into the paused state and then report the
// relationship between the media and reference timelines which was
// established (if requested).
//
// If omitted, the media time to be paused at will be determined by the
// current relationship between the media timeline and its reference timeline,
// as determined by the previously delivered play command.
//
// TODO(mpuryear): Define behavior in the case that a user calls Pause while
// the system is already in the paused state. We should probably do nothing
// but provide a valid correspondence pair in response unless an explicit
// media time is provided, in which case we should redefine the resume time,
// introducing a discontinuity in the process.
//
// TODO(mpuryear): Collapse these if we ever have optional retvals in FIDL
0x0608: Pause() -> (int64 reference_time, int64 media_time);
0x0609: PauseNoReply();
// Enable or disable notifications about changes to the minimim clock lead
// time (in nanoseconds) for this AudioOut. Calling this method with
// enabled set to true will trigger an immediate OnMinLeadTimeChanged event
// with the current minimum lead time for the AudioOut. If the value changes,
// an OnMinLeadTimeChanged event will be raise with the new value. This
// behavior will continue until the user calls Enable with enabled set to
// false.
//
// TODO(mpuryear): Should Enable have an optional -> () return value for
// synchronization purposes? Probably not; users should be able to simply
// send a disable request and clear their event handler if they no longer care
// to receive notifications. Their in-process dispatcher framework can handle
// draining and dropping any lead time changed events that were already in
// flight when the disable message was sent.
//
// The minimum clock lead time is the amount of time ahead of RefClock.Now()
// packets needs to arrive ahead of the playback clock transformation in order
// for the mixer to be able to mix packet. For example...
//
// ++ Let the PTS of packet X be P(X)
// ++ Let the function which transforms PTS -> RefClock be R(p) (this function
// is determined by the call to Play(...)
// ++ Let the minimum lead time be MLT
//
// If R(P(X)) < RefClock.Now() + MLT
// Then the packet is late, and some (or all) of the packet's payload will
// need to be skipped in order to present the packet at the scheduled time.
//
// TODO(mpuryear): What should the units be here? Options include...
//
// 1) Normalized to nanoseconds (this is the current API)
// 2) Reference clock units (what happens if the reference clock changes?)
// 3) PTS units (what happens when the user changes the PTS units?)
//
0x060a: EnableMinLeadTimeEvents(bool enabled);
0x060b: -> OnMinLeadTimeChanged(int64 min_lead_time_nsec);
// TODO(mpuryear): Get rid of this method when possible. Right now, it is
// used by code which demands to use a synchronous FIDL interface to talk to
// AudioOuts.
0x060c: GetMinLeadTime() -> (int64 min_lead_time_nsec);
// Binds to the gain control for this AudioOut.
0x060d: BindGainControl(request<GainControl> gain_control_request);
/////////////////////////////////////////////////////////////////////////////
// StreamBufferSet methods
// These methods will inherited from the StreamBufferSet interface.
// Add a payload buffer for stream packets.
0x0201: AddPayloadBuffer(uint32 id, handle<vmo> payload_buffer);
// Remove a payload buffer.
0x0202: RemovePayloadBuffer(uint32 id);
/////////////////////////////////////////////////////////////////////////////
// StreamSink methods
// These methods will inherited from the StreamSink interface.
// Sends a packet to this object. The response is sent when this object is
// done with the associated payload memory.
0x0301: SendPacket(StreamPacket packet) -> ();
// Sends a packet to this object. This interface doesn't define how the client
// knows when the sink is done with the associated payload memory. The
// inheriting interface must define that.
0x0302: SendPacketNoReply(StreamPacket packet);
// Indicates the stream has ended.
0x0303: EndOfStream();
// Discards packets previous sent via SendPacket or SendPacketNoReply.
0x0304: DiscardAllPackets() -> ();
0x0305: DiscardAllPacketsNoReply();
// TODO(mpuryear): Spec methods/events which can be used for unintentional
// discontinuity/underflow detection.
//
// TODO(mpuryear): Spec methods/events which can be used to report routing
// changes. (Presuming that they belong at this level at all; they may belong
// on some sort of policy object).
//
// TODO(mpuryear): Spec methods/events which can be used to report policy
// induced gain/ducking changes. (Presuming that they belong at this level at
// all; they may belong on some sort of policy object).
};