Index: services/media/audio/audio_track_to_output_link.h |
diff --git a/services/media/audio/audio_track_to_output_link.h b/services/media/audio/audio_track_to_output_link.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f9d31ec1d2a6302540175e4c2549856553cadadf |
--- /dev/null |
+++ b/services/media/audio/audio_track_to_output_link.h |
@@ -0,0 +1,128 @@ |
+// 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_AUDIO_AUDIO_TRACK_TO_OUTPUT_LINK_H_ |
+#define SERVICES_MEDIA_AUDIO_AUDIO_TRACK_TO_OUTPUT_LINK_H_ |
+ |
+#include <deque> |
+#include <memory> |
+ |
+#include "base/synchronization/lock.h" |
+#include "services/media/audio/audio_pipe.h" |
+#include "services/media/audio/fwd_decls.h" |
+ |
+namespace mojo { |
+namespace media { |
+namespace audio { |
+ |
+// AudioTrackToOutputLink is a small class which tracks the relationship between |
+// an audio track and an audio output. Tracks and outputs are expected to hold |
+// strong pointers to the state in the collections they use to track their |
+// peers. |
+// |
+// When either a track or an output ceases to exist, its collection will clear |
+// releasing the reference to the shared state. When the other half of the |
+// relationship realizes that its peer has gone away (typically by failing to |
+// promote the weak reference to its peer held in the share state object), it |
+// can purge the state object strong pointer from its collection triggering the |
+// final cleanup of the shared state. |
+// |
+// Because the final cleanup of the shared state can be triggered either from an |
+// output manager mixer thread, or from the audio service's main message loop, |
+// it must be safe to destruct all of the shared state from any thread in the |
+// system. No assumptions may be made about threading when destructing. |
jeffbrown
2015/11/04 23:43:34
This could be amended by making the cleanup signal
johngro
2015/11/06 02:20:26
Acknowledged.
|
+// |
+// The AudioTrackToOutputLink object holds a queue of pending audio packet |
+// references sourced from the AudioTrack to be rendered on the audio output. |
+// The references are safe to release either from an output manager thread, or |
+// from the audio service's main message loop thread (which drives track |
+// behavior). |
+// |
+// Finally, both the Output may have a pointer to a Bookkeeping object in order |
+// to manage bookkeeping tasks specific to the Track/Output relationship. The |
+// following rules must be obeyed at all times... |
+// |
+// + Derrived classes of the Bookkeeping object created by the Output must be |
+// safe to destroy either thread. During destruction, no potentially blocking |
+// operations may be performed. No heavy operations (such as logging) should |
+// be performed. |
+// + Only the output is permitted to access the output bookkeeping. The track |
+// must make no attempts to modify the bookkeeping or its pointer. |
+// + Outputs must hold a strong reference to the shared link object object |
+// whenever they are accessing their bookkeeping object. The link object is |
+// considered to be the owner of the Bookkeeping, users must never hold a |
+// naked pointer to their bookkeeping if the link could possibly destruct. |
+// |
+class AudioTrackToOutputLink { |
+ public: |
+ struct Bookkeeping { |
+ virtual ~Bookkeeping(); |
+ }; |
+ |
+ using BookkeepingPtr = std::unique_ptr<Bookkeeping>; |
+ using PacketQueue = std::deque<AudioPipe::AudioPacketRefPtr>; |
+ using PacketQueuePtr = std::unique_ptr<PacketQueue>; |
+ |
+ static AudioTrackToOutputLinkPtr New(AudioTrackImplWeakPtr track, |
+ AudioOutputWeakPtr output); |
+ virtual ~AudioTrackToOutputLink(); |
+ |
+ // Accessors for the track and output pointers. Automatically attempts to |
+ // promote the weak pointer to a strong pointer. |
+ // |
+ // TODO(johngro): Given the way outputs are currently shut down, there is |
+ // actually no need for the link to hold a weak pointer to output. By the |
+ // time it destructs, All references to it are guaranteed to have been removed |
+ // from all tracks in the context of the main event loop. Consider converting |
+ // this from a weak pointer to a strong pointer. |
+ AudioTrackImplPtr GetTrack() { return track_.lock(); } |
+ AudioOutputPtr GetOutput() { return output_.lock(); } |
+ |
+ // AudioTrack PendingQueue operations. Never call these from the AudioOutput. |
+ void PushToPendingQueue(const AudioPipe::AudioPacketRefPtr& pkt); |
+ void FlushPendingQueue(); |
+ |
+ // AudioOutput PendingQueue operations. Never call these from the AudioTrack. |
+ // When consuming audio, AudioOutputs must always pair their calls to |
+ // LockPendingQueueFront and UnlockPendingQueueFront, passing the pointer to |
+ // the reference to the front of the queue they obtained in the process (even |
+ // if the front of the queue was nullptr). |
+ // |
+ // Doing so ensures that AudioTracks which are attempting to flush the pending |
+ // queue are forced to wait if the front of the queue is involved in a mixing |
+ // operation. This, in turn, guarantees that audio packets are always |
+ // returned to the user in the order which they were queued in without forcing |
+ // AudioTracks to wait to queue new data if a mix operation is in progress. |
+ AudioPipe::AudioPacketRefPtr LockPendingQueueFront(bool* was_flushed); |
+ void UnlockPendingQueueFront(AudioPipe::AudioPacketRefPtr* pkt, |
+ bool release_packet); |
+ |
+ // Bookkeeping access. |
+ // |
+ BookkeepingPtr& output_bookkeeping() { return output_bookkeeping_; } |
+ |
+ private: |
+ void ReleaseQueue(const PacketQueuePtr& queue); |
+ |
+ AudioTrackToOutputLink(AudioTrackImplWeakPtr track, |
+ AudioOutputWeakPtr output); |
+ |
+ AudioTrackImplWeakPtr track_; |
+ AudioOutputWeakPtr output_; |
+ BookkeepingPtr output_bookkeeping_; |
+ |
+ base::Lock flush_lock_; |
+ base::Lock pending_queue_lock_; |
+ PacketQueuePtr pending_queue_; |
+ bool flushed_ = true; |
+#if !(defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)) |
+ std::atomic<bool> flush_lock_held_; |
+#endif |
+}; |
+ |
+} // namespace audio |
+} // namespace media |
+} // namespace mojo |
+ |
+#endif // SERVICES_MEDIA_AUDIO_AUDIO_TRACK_TO_OUTPUT_LINK_H_ |