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

Side by Side Diff: services/media/audio/platform/generic/standard_output_base.cc

Issue 1471813002: Mix to an intermediate buffer. (Closed) Base URL: https://github.com/domokit/mojo.git@change7
Patch Set: Final rebase before landing Created 4 years, 10 months 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits> 5 #include <limits>
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "services/media/audio/audio_track_impl.h" 8 #include "services/media/audio/audio_track_impl.h"
9 #include "services/media/audio/audio_track_to_output_link.h" 9 #include "services/media/audio/audio_track_to_output_link.h"
10 #include "services/media/audio/platform/generic/mixer.h" 10 #include "services/media/audio/platform/generic/mixer.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 71
72 // As long as our implementation wants to mix more and has not run into a 72 // As long as our implementation wants to mix more and has not run into a
73 // problem trying to finish the mix job, mix some more. 73 // problem trying to finish the mix job, mix some more.
74 do { 74 do {
75 ::memset(&cur_mix_job_, 0, sizeof(cur_mix_job_)); 75 ::memset(&cur_mix_job_, 0, sizeof(cur_mix_job_));
76 76
77 if (!StartMixJob(&cur_mix_job_, now)) { 77 if (!StartMixJob(&cur_mix_job_, now)) {
78 break; 78 break;
79 } 79 }
80 80
81 // If we have a mix job, then we must have an output formatter, and an
82 // intermediate buffer allocated, and it must be large enough for the mix
83 // job we were given.
84 DCHECK(mix_buf_);
85 DCHECK(output_formatter_);
86 DCHECK_LE(cur_mix_job_.buf_frames, mix_buf_frames_);
87
88 // Fill the intermediate buffer with silence.
89 size_t bytes_to_zero = sizeof(*mix_buf_)
90 * cur_mix_job_.buf_frames
91 * output_formatter_->channels();
92 ::memset(mix_buf_.get(), 0, bytes_to_zero);
93
94 // Mix each track into the intermediate buffer, then clip/format into the
95 // final buffer.
81 ForeachTrack(setup_mix_, process_mix_); 96 ForeachTrack(setup_mix_, process_mix_);
97 output_formatter_->ProduceOutput(mix_buf_.get(),
98 cur_mix_job_.buf,
99 cur_mix_job_.buf_frames);
100
82 mixed = true; 101 mixed = true;
83 } while (FinishMixJob(cur_mix_job_)); 102 } while (FinishMixJob(cur_mix_job_));
84 } 103 }
85 104
86 if (!next_sched_time_known_) { 105 if (!next_sched_time_known_) {
87 // TODO(johngro): log this as an error. 106 // TODO(johngro): log this as an error.
88 ShutdownSelf(); 107 ShutdownSelf();
89 return; 108 return;
90 } 109 }
91 110
(...skipping 20 matching lines...) Expand all
112 131
113 // We should never fail to allocate our bookkeeping. The only way this can 132 // We should never fail to allocate our bookkeeping. The only way this can
114 // happen is if we have a badly behaved implementation. 133 // happen is if we have a badly behaved implementation.
115 if (!bk) { return MediaResult::INTERNAL_ERROR; } 134 if (!bk) { return MediaResult::INTERNAL_ERROR; }
116 135
117 // We cannot proceed if our track has somehow managed to go away already. 136 // We cannot proceed if our track has somehow managed to go away already.
118 AudioTrackImplPtr track = link->GetTrack(); 137 AudioTrackImplPtr track = link->GetTrack();
119 if (!track) { return MediaResult::INVALID_ARGUMENT; } 138 if (!track) { return MediaResult::INVALID_ARGUMENT; }
120 139
121 // Pick a mixer based on the input and output formats. 140 // Pick a mixer based on the input and output formats.
122 bk->mixer = Mixer::Select(track->Format(), output_format_); 141 bk->mixer = Mixer::Select(track->Format(), output_formatter_
142 ? &output_formatter_->format()
143 : nullptr);
123 if (bk->mixer == nullptr) { return MediaResult::UNSUPPORTED_CONFIG; } 144 if (bk->mixer == nullptr) { return MediaResult::UNSUPPORTED_CONFIG; }
124 145
125 // Looks like things went well. Stash a reference to our bookkeeping and get 146 // Looks like things went well. Stash a reference to our bookkeeping and get
126 // out. 147 // out.
127 link->output_bookkeeping() = std::move(ref); 148 link->output_bookkeeping() = std::move(ref);
128 return MediaResult::OK; 149 return MediaResult::OK;
129 } 150 }
130 151
131 StandardOutputBase::TrackBookkeeping* StandardOutputBase::AllocBookkeeping() { 152 StandardOutputBase::TrackBookkeeping* StandardOutputBase::AllocBookkeeping() {
132 return new TrackBookkeeping(); 153 return new TrackBookkeeping();
133 } 154 }
134 155
156 void StandardOutputBase::SetupMixBuffer(uint32_t max_mix_frames) {
157 DCHECK_GT(output_formatter_->channels(), 0u);
158 DCHECK_GT(max_mix_frames, 0u);
159 DCHECK_LE(max_mix_frames, std::numeric_limits<uint32_t>::max() /
160 output_formatter_->channels());
161
162 mix_buf_frames_ = max_mix_frames;
163 mix_buf_.reset(new int32_t[mix_buf_frames_ * output_formatter_->channels()]);
164 }
165
135 void StandardOutputBase::ForeachTrack(const TrackSetupTask& setup, 166 void StandardOutputBase::ForeachTrack(const TrackSetupTask& setup,
136 const TrackProcessTask& process) { 167 const TrackProcessTask& process) {
137 for (auto iter = links_.begin(); iter != links_.end(); ) { 168 for (auto iter = links_.begin(); iter != links_.end(); ) {
138 if (shutting_down()) { return; } 169 if (shutting_down()) { return; }
139 170
140 // Is the track still around? If so, process it. Otherwise, remove the 171 // Is the track still around? If so, process it. Otherwise, remove the
141 // track entry and move on. 172 // track entry and move on.
142 const AudioTrackToOutputLinkPtr& link = *iter; 173 const AudioTrackToOutputLinkPtr& link = *iter;
143 AudioTrackImplPtr track(link->GetTrack()); 174 AudioTrackImplPtr track(link->GetTrack());
144 175
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 242
212 bool StandardOutputBase::ProcessMix( 243 bool StandardOutputBase::ProcessMix(
213 const AudioTrackImplPtr& track, 244 const AudioTrackImplPtr& track,
214 TrackBookkeeping* info, 245 TrackBookkeeping* info,
215 const AudioPipe::AudioPacketRefPtr& packet) { 246 const AudioPipe::AudioPacketRefPtr& packet) {
216 // Sanity check our parameters. 247 // Sanity check our parameters.
217 DCHECK(info); 248 DCHECK(info);
218 DCHECK(packet); 249 DCHECK(packet);
219 250
220 // We had better have a valid job, or why are we here? 251 // We had better have a valid job, or why are we here?
221 DCHECK(cur_mix_job_.buf);
222 DCHECK(cur_mix_job_.buf_frames); 252 DCHECK(cur_mix_job_.buf_frames);
223 DCHECK(cur_mix_job_.frames_produced <= cur_mix_job_.buf_frames); 253 DCHECK(cur_mix_job_.frames_produced <= cur_mix_job_.buf_frames);
224 254
225 // We also must have selected a mixer, or we are in trouble. 255 // We also must have selected a mixer, or we are in trouble.
226 DCHECK(info->mixer); 256 DCHECK(info->mixer);
227 Mixer& mixer = *(info->mixer); 257 Mixer& mixer = *(info->mixer);
228 258
229 // If this track is currently paused (or being sampled extremely slowly), our 259 // If this track is currently paused (or being sampled extremely slowly), our
230 // step size will be zero. We know that this packet will be relevant at some 260 // step size will be zero. We know that this packet will be relevant at some
231 // point in the future, but right now it contributes nothing. Tell the 261 // point in the future, but right now it contributes nothing. Tell the
232 // ForeachTrack loop that we are done and to hold onto this packet for now. 262 // ForeachTrack loop that we are done and to hold onto this packet for now.
233 if (!info->step_size) { 263 if (!info->step_size) {
234 return false; 264 return false;
235 } 265 }
236 266
237 // Have we produced all that we are supposed to? If so, hold the current 267 // Have we produced all that we are supposed to? If so, hold the current
238 // packet and move on to the next track. 268 // packet and move on to the next track.
239 if (cur_mix_job_.frames_produced >= cur_mix_job_.buf_frames) { 269 if (cur_mix_job_.frames_produced >= cur_mix_job_.buf_frames) {
240 return false; 270 return false;
241 } 271 }
242 272
243 uint32_t frames_left = cur_mix_job_.buf_frames - cur_mix_job_.frames_produced; 273 uint32_t frames_left = cur_mix_job_.buf_frames - cur_mix_job_.frames_produced;
244 void* buf = static_cast<uint8_t*>(cur_mix_job_.buf) 274 int32_t* buf = mix_buf_.get()
245 + (cur_mix_job_.frames_produced * output_bytes_per_frame_); 275 + (cur_mix_job_.frames_produced * output_formatter_->channels());
246 276
247 // Figure out where the first and last sampling points of this job are, 277 // Figure out where the first and last sampling points of this job are,
248 // expressed in fractional track frames. 278 // expressed in fractional track frames.
249 int64_t first_sample_ftf; 279 int64_t first_sample_ftf;
250 bool good = info->out_frames_to_track_frames.DoForwardTransform( 280 bool good = info->out_frames_to_track_frames.DoForwardTransform(
251 cur_mix_job_.start_pts_of + cur_mix_job_.frames_produced, 281 cur_mix_job_.start_pts_of + cur_mix_job_.frames_produced,
252 &first_sample_ftf); 282 &first_sample_ftf);
253 DCHECK(good); 283 DCHECK(good);
254 284
255 DCHECK(frames_left); 285 DCHECK(frames_left);
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 step_size = static_cast<uint32_t>(tmp_step_size); 528 step_size = static_cast<uint32_t>(tmp_step_size);
499 } 529 }
500 530
501 // Done, update our generation. 531 // Done, update our generation.
502 out_frames_to_track_frames_gen = job.local_to_output_gen; 532 out_frames_to_track_frames_gen = job.local_to_output_gen;
503 } 533 }
504 534
505 } // namespace audio 535 } // namespace audio
506 } // namespace media 536 } // namespace media
507 } // namespace mojo 537 } // namespace mojo
OLDNEW
« no previous file with comments | « services/media/audio/platform/generic/standard_output_base.h ('k') | services/media/audio/platform/linux/alsa_output.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698