| 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..9c3702cb035e0640292d33fe4e8a3bb1960052aa
|
| --- /dev/null
|
| +++ b/services/media/audio/audio_pipe.cc
|
| @@ -0,0 +1,131 @@
|
| +// 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, // NOLINT(build/c++11)
|
| + int64_t start_pts,
|
| + int64_t end_pts)
|
| + : state_(std::move(state)),
|
| + server_(server),
|
| + regions_(std::move(regions)),
|
| + start_pts_(start_pts),
|
| + end_pts_(end_pts) {
|
| + DCHECK(state_);
|
| + DCHECK(server_);
|
| +}
|
| +
|
| +AudioPipe::AudioPacketRef::~AudioPacketRef() {
|
| + DCHECK(server_);
|
| + server_->SchedulePacketCleanup(std::move(state_));
|
| +}
|
| +
|
| +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;
|
| +
|
| + 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);
|
| + 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,
|
| + 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),
|
| + 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
|
|
|