Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: services/media/audio/audio_track_to_output_link.cc

Issue 1424933002: Add an initial revision of an audio server. (Closed) Base URL: https://github.com/domokit/mojo.git@change4
Patch Set: refactor MixerKernel into a class to prepare for the addition of a linear interpolation sampler Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 #include "base/logging.h"
6 #include "services/media/audio/audio_track_to_output_link.h"
7
8 namespace mojo {
9 namespace media {
10 namespace audio {
11
12 AudioTrackToOutputLink::Bookkeeping::~Bookkeeping() {}
13
14 AudioTrackToOutputLink::AudioTrackToOutputLink(AudioTrackImplWeakPtr track,
15 AudioOutputWeakPtr output)
16 : track_(track),
17 output_(output),
18 pending_queue_(new PacketQueue) {
19 #if !(defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON))
20 flush_lock_held_ = false;
21 #endif
22 }
23
24 AudioTrackToOutputLink::~AudioTrackToOutputLink() {
25 ReleaseQueue(pending_queue_);
26 }
27
28 AudioTrackToOutputLinkPtr AudioTrackToOutputLink::New(
29 AudioTrackImplWeakPtr track,
30 AudioOutputWeakPtr output) {
31 return AudioTrackToOutputLinkPtr(new AudioTrackToOutputLink(track, output));
32 }
33
34 void AudioTrackToOutputLink::PushToPendingQueue(
35 const AudioPipe::AudioPacketRefPtr& pkt) {
36 base::AutoLock lock(pending_queue_lock_);
37 pending_queue_->emplace_back(pkt);
38 }
39
40 void AudioTrackToOutputLink::FlushPendingQueue() {
41 // Create a new (empty) queue before obtaining any locks. This will allow us
42 // to quickly swap the empty queue for the current queue and get out of all
43 // the locks, and then release the packets at our leisure instead of
44 // potentially holding off a high priority mixing thread while releasing
45 // packets.
46 //
47 // Note: the safety of this technique depends on Flush only ever being called
48 // from the AudioTrack, and the AudioTrack's actions being serialized on the
49 // AudioServer's message loop thread. If multiple flushes are allowed to be
50 // invoked simultaniously, or if a packet is permitted to be added to the
51 // queue while a flush operation is in progress, it is possible to return
52 // packets to the user in an order different than the one that they were
53 // queued in.
jeffbrown 2015/11/04 23:43:34 FWIW, we might actually find it worthwhile to push
johngro 2015/11/06 02:20:26 As discussed F2F yesterday, this will add a ton of
54 PacketQueuePtr new_queue(new PacketQueue);
55
56 {
57 base::AutoLock lock(flush_lock_);
58 {
59 // TODO(johngro): Assuming that it is impossible to push a new packet
60 // while a flush is in progress, it's pretty easy to show that this lock
61 // can never be contended. Because of this, we could consider removing
62 // this lock operation (although, flush is a relatively rare operation, so
63 // the extra overhead is pretty insignificant.
64 base::AutoLock lock(pending_queue_lock_);
65 pending_queue_.swap(new_queue);
66 }
67 flushed_ = true;
68 }
69
70 ReleaseQueue(new_queue);
71 }
72
73 AudioPipe::AudioPacketRefPtr AudioTrackToOutputLink::LockPendingQueueFront(
74 bool* was_flushed) {
75 #if !(defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON))
76 // No one had better be holding the flush lock right now. If someone is, then
77 // we either have multiple threads hitting this operation at the same time
78 // (should be impossible), or an audio output forgot to unlock the front of
79 // the queue before attempting to lock it again.
80 bool was_held = false;
81 flush_lock_held_.compare_exchange_strong(was_held, true);
82 DCHECK(!was_held);
83 #endif
84 flush_lock_.Acquire();
85
86 DCHECK(was_flushed);
87 *was_flushed = flushed_;
88 flushed_ = false;
89
90 {
91 base::AutoLock lock(pending_queue_lock_);
92 if (pending_queue_->size()) {
93 return pending_queue_->front();
94 } else {
95 return nullptr;
96 }
97 }
98 }
99
100 void AudioTrackToOutputLink::UnlockPendingQueueFront(
101 AudioPipe::AudioPacketRefPtr* pkt,
102 bool release_packet) {
103 {
104 base::AutoLock lock(pending_queue_lock_);
105
106 // Assert that the user either got no packet when they locked the queue
107 // (because the queue was empty), or that they got the front of the queue
108 // and that the front of the queue has not changed.
109 DCHECK(pkt);
110 DCHECK((*pkt == nullptr) ||
111 (pending_queue_->size() && (*pkt == pending_queue_->front())));
112
113 if (*pkt) {
114 *pkt = nullptr;
115 if (release_packet) {
116 pending_queue_->pop_front();
117 }
118 }
119 }
120
121 flush_lock_.Release();
122 #if !(defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON))
123 bool was_held = true;
124 flush_lock_held_.compare_exchange_strong(was_held, false);
125 DCHECK(was_held);
126 #endif
127 }
128
129 void AudioTrackToOutputLink::ReleaseQueue(const PacketQueuePtr& queue) {
130 if (!queue) {
131 return;
132 }
133
134 for (auto iter = queue->begin(); iter != queue->end(); ++iter) {
135 (*iter).reset();
136 }
137
138 queue->clear();
139 }
140
141 } // namespace audio
142 } // namespace media
143 } // namespace mojo
144
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698