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. | |
jeffbrown
2015/11/04 23:43:34
This could be amended by making the cleanup signal
johngro
2015/11/06 02:20:26
Acknowledged.
| |
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 |