OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef SERVICES_MEDIA_AUDIO_AUDIO_TRACK_TO_OUTPUT_LINK_H_ |
| 6 #define SERVICES_MEDIA_AUDIO_AUDIO_TRACK_TO_OUTPUT_LINK_H_ |
| 7 |
| 8 #include <deque> |
| 9 #include <memory> |
| 10 |
| 11 #include "base/synchronization/lock.h" |
| 12 #include "services/media/audio/audio_pipe.h" |
| 13 #include "services/media/audio/fwd_decls.h" |
| 14 |
| 15 namespace mojo { |
| 16 namespace media { |
| 17 namespace audio { |
| 18 |
| 19 // AudioTrackToOutputLink is a small class which tracks the relationship between |
| 20 // an audio track and an audio output. Tracks and outputs are expected to hold |
| 21 // strong pointers to the state in the collections they use to track their |
| 22 // peers. |
| 23 // |
| 24 // When either a track or an output ceases to exist, its collection will clear |
| 25 // releasing the reference to the shared state. When the other half of the |
| 26 // relationship realizes that its peer has gone away (typically by failing to |
| 27 // promote the weak reference to its peer held in the share state object), it |
| 28 // can purge the state object strong pointer from its collection triggering the |
| 29 // final cleanup of the shared state. |
| 30 // |
| 31 // Because the final cleanup of the shared state can be triggered either from an |
| 32 // output manager mixer thread, or from the audio service's main message loop, |
| 33 // it must be safe to destruct all of the shared state from any thread in the |
| 34 // system. No assumptions may be made about threading when destructing. |
| 35 // |
| 36 // The AudioTrackToOutputLink object holds a queue of pending audio packet |
| 37 // references sourced from the AudioTrack to be rendered on the audio output. |
| 38 // The references are safe to release either from an output manager thread, or |
| 39 // from the audio service's main message loop thread (which drives track |
| 40 // behavior). |
| 41 // |
| 42 // Finally, both the Output may have a pointer to a Bookkeeping object in order |
| 43 // to manage bookkeeping tasks specific to the Track/Output relationship. The |
| 44 // following rules must be obeyed at all times... |
| 45 // |
| 46 // + Derrived classes of the Bookkeeping object created by the Output must be |
| 47 // safe to destroy either thread. During destruction, no potentially blocking |
| 48 // operations may be performed. No heavy operations (such as logging) should |
| 49 // be performed. |
| 50 // + Only the output is permitted to access the output bookkeeping. The track |
| 51 // must make no attempts to modify the bookkeeping or its pointer. |
| 52 // + Outputs must hold a strong reference to the shared link object object |
| 53 // whenever they are accessing their bookkeeping object. The link object is |
| 54 // considered to be the owner of the Bookkeeping, users must never hold a |
| 55 // naked pointer to their bookkeeping if the link could possibly destruct. |
| 56 // |
| 57 class AudioTrackToOutputLink { |
| 58 public: |
| 59 struct Bookkeeping { |
| 60 virtual ~Bookkeeping(); |
| 61 }; |
| 62 |
| 63 using BookkeepingPtr = std::unique_ptr<Bookkeeping>; |
| 64 using PacketQueue = std::deque<AudioPipe::AudioPacketRefPtr>; |
| 65 using PacketQueuePtr = std::unique_ptr<PacketQueue>; |
| 66 |
| 67 static AudioTrackToOutputLinkPtr New(AudioTrackImplWeakPtr track, |
| 68 AudioOutputWeakPtr output); |
| 69 virtual ~AudioTrackToOutputLink(); |
| 70 |
| 71 // Accessors for the track and output pointers. Automatically attempts to |
| 72 // promote the weak pointer to a strong pointer. |
| 73 // |
| 74 // TODO(johngro): Given the way outputs are currently shut down, there is |
| 75 // actually no need for the link to hold a weak pointer to output. By the |
| 76 // time it destructs, All references to it are guaranteed to have been removed |
| 77 // from all tracks in the context of the main event loop. Consider converting |
| 78 // this from a weak pointer to a strong pointer. |
| 79 AudioTrackImplPtr GetTrack() { return track_.lock(); } |
| 80 AudioOutputPtr GetOutput() { return output_.lock(); } |
| 81 |
| 82 // AudioTrack PendingQueue operations. Never call these from the AudioOutput. |
| 83 void PushToPendingQueue(const AudioPipe::AudioPacketRefPtr& pkt); |
| 84 void FlushPendingQueue(); |
| 85 |
| 86 // AudioOutput PendingQueue operations. Never call these from the AudioTrack. |
| 87 // When consuming audio, AudioOutputs must always pair their calls to |
| 88 // LockPendingQueueFront and UnlockPendingQueueFront, passing the pointer to |
| 89 // the reference to the front of the queue they obtained in the process (even |
| 90 // if the front of the queue was nullptr). |
| 91 // |
| 92 // Doing so ensures that AudioTracks which are attempting to flush the pending |
| 93 // queue are forced to wait if the front of the queue is involved in a mixing |
| 94 // operation. This, in turn, guarantees that audio packets are always |
| 95 // returned to the user in the order which they were queued in without forcing |
| 96 // AudioTracks to wait to queue new data if a mix operation is in progress. |
| 97 AudioPipe::AudioPacketRefPtr LockPendingQueueFront(bool* was_flushed); |
| 98 void UnlockPendingQueueFront(AudioPipe::AudioPacketRefPtr* pkt, |
| 99 bool release_packet); |
| 100 |
| 101 // Bookkeeping access. |
| 102 // |
| 103 BookkeepingPtr& output_bookkeeping() { return output_bookkeeping_; } |
| 104 |
| 105 private: |
| 106 void ReleaseQueue(const PacketQueuePtr& queue); |
| 107 |
| 108 AudioTrackToOutputLink(AudioTrackImplWeakPtr track, |
| 109 AudioOutputWeakPtr output); |
| 110 |
| 111 AudioTrackImplWeakPtr track_; |
| 112 AudioOutputWeakPtr output_; |
| 113 BookkeepingPtr output_bookkeeping_; |
| 114 |
| 115 base::Lock flush_lock_; |
| 116 base::Lock pending_queue_lock_; |
| 117 PacketQueuePtr pending_queue_; |
| 118 bool flushed_ = true; |
| 119 #if !(defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)) |
| 120 std::atomic<bool> flush_lock_held_; |
| 121 #endif |
| 122 }; |
| 123 |
| 124 } // namespace audio |
| 125 } // namespace media |
| 126 } // namespace mojo |
| 127 |
| 128 #endif // SERVICES_MEDIA_AUDIO_AUDIO_TRACK_TO_OUTPUT_LINK_H_ |
OLD | NEW |