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

Unified Diff: services/media/audio/audio_pipe.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 side-by-side diff with in-line comments
Download patch
Index: services/media/audio/audio_pipe.cc
diff --git a/services/media/audio/audio_pipe.cc b/services/media/audio/audio_pipe.cc
new file mode 100644
index 0000000000000000000000000000000000000000..57823717791d155e9f285e4bca677d9d7d6acea7
--- /dev/null
+++ b/services/media/audio/audio_pipe.cc
@@ -0,0 +1,130 @@
+// 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.
+
+#include <limits>
+#include <vector>
+
+#include "services/media/audio/audio_pipe.h"
+#include "services/media/audio/audio_server_impl.h"
+#include "services/media/audio/audio_track_impl.h"
+
+namespace mojo {
+namespace media {
+namespace audio {
+
+AudioPipe::AudioPacketRef::AudioPacketRef(MediaPacketStatePtr state,
+ AudioServerImpl* server,
+ std::vector<Region>&& regions,
+ int64_t start_pts,
+ int64_t end_pts)
+ : state_(std::move(state)),
+ server_(server),
+ regions_(regions),
+ start_pts_(start_pts),
+ end_pts_(end_pts) {
+ DCHECK(state_);
+ DCHECK(server_);
+}
+
+AudioPipe::AudioPacketRef::~AudioPacketRef() {
+ DCHECK(server_);
+ server_->SchedulePacketCleanup(std::move(state_));
jeffbrown 2015/11/04 23:43:33 Destructor side-effects like these make be a littl
johngro 2015/11/06 02:20:25 yeah, I am not thrilled with this either. It is a
+}
+
+AudioPipe::AudioPipe(AudioTrackImpl* owner,
+ AudioServerImpl* server)
+ : owner_(owner),
+ server_(server) {
+ DCHECK(owner_);
+ DCHECK(server_);
+}
+
+AudioPipe::~AudioPipe() {}
+
+void AudioPipe::OnPacketReceived(MediaPacketStatePtr state) {
+ const MediaPacketPtr& packet = state->GetPacket();
+ DCHECK(packet);
+ DCHECK(packet->payload);
+ DCHECK(owner_);
+
+ // Start by making sure that we are regions we are receiving are made from an
+ // integral number of audio frames. Count the total number of frames in the
+ // process.
+ //
+ // TODO(johngro): Someday, automatically enforce this using
+ // alignment/allocation restrictions at the MediaPipe level of things.
+ uint32_t frame_count = 0;
+ uint32_t frame_size = owner_->BytesPerFrame();
+ const MediaPacketRegionPtr* region = &packet->payload;
+ size_t ndx = 0;
+ std::vector<AudioPacketRef::Region> regions;
jeffbrown 2015/11/04 23:43:33 I was slightly surprised to see you allocating on
johngro 2015/11/06 02:20:25 I was made slightly ill by my actions in doing so.
+
+ regions.reserve(packet->extra_payload.size() + 1);
+
+ DCHECK(frame_size);
+ while (true) {
+ if ((frame_size > 1) && ((*region)->length % frame_size)) {
+ state->SetResult(MediaResult::INVALID_ARGUMENT);
jeffbrown 2015/11/04 23:43:33 can we just close the pipe?
johngro 2015/11/06 02:20:25 Acknowledged. Placing the general close-the-pipe-a
+ return;
+ }
+
+ frame_count += ((*region)->length / frame_size);
+ if (frame_count > (std::numeric_limits<uint32_t>::max() >>
+ AudioTrackImpl::PTS_FRACTIONAL_BITS)) {
+ state->SetResult(MediaResult::INVALID_ARGUMENT);
+ return;
+ }
+
+ regions.emplace_back(
+ static_cast<const uint8_t*>(buffer()) + (*region)->offset,
jeffbrown 2015/11/04 23:43:33 Make sure to check that the offset is within the b
johngro 2015/11/06 02:20:25 Offset and length containment has already been han
+ frame_count << AudioTrackImpl::PTS_FRACTIONAL_BITS);
+
+ if (ndx >= packet->extra_payload.size()) {
+ break;
+ }
+
+ region = &(packet->extra_payload[ndx]);
+ ndx++;
+ }
+
+ // Figure out the starting PTS.
+ int64_t start_pts;
+ if (packet->pts != MediaPacket::kNoTimestamp) {
+ // The user provided an explicit PTS for this audio. Transform it into
+ // units of fractional frames.
+ LinearTransform tmp(0, owner_->FractionalFrameToMediaTimeRatio(), 0);
+ if (!tmp.DoForwardTransform(packet->pts, &start_pts)) {
+ state->SetResult(MediaResult::INTERNAL_ERROR);
+ return;
+ }
+ } else {
+ // No PTS was provided. Use the end time of the last audio packet, if
+ // known. Otherwise, just assume a media time of 0.
+ start_pts = next_pts_known_ ? next_pts_ : 0;
+ }
+
+ // The end pts is the value we will use for the next packet's start PTS, if
+ // the user does not provide an explicit PTS.
+ int64_t pts_delta = (static_cast<int64_t>(frame_count)
+ << AudioTrackImpl::PTS_FRACTIONAL_BITS);
+ next_pts_ = start_pts + pts_delta;
+ next_pts_known_ = true;
+
+ owner_->OnPacketReceived(AudioPacketRefPtr(
+ new AudioPacketRef(std::move(state),
+ server_,
+ std::move(regions),
jeffbrown 2015/11/04 23:43:33 So this object contains a pointer to an mmap'd reg
johngro 2015/11/06 02:20:25 FWIW - enforcement like this belong at the MediaPi
+ start_pts,
+ next_pts_)));
+}
+
+void AudioPipe::OnFlushRequested(const FlushCallback& cbk) {
+ DCHECK(owner_);
+ owner_->OnFlushRequested(cbk);
+ next_pts_known_ = false;
+}
+
+} // namespace audio
+} // namespace media
+} // namespace mojo

Powered by Google App Engine
This is Rietveld 408576698