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 #include <limits> |
| 6 #include <vector> |
| 7 |
| 8 #include "services/media/audio/audio_pipe.h" |
| 9 #include "services/media/audio/audio_server_impl.h" |
| 10 #include "services/media/audio/audio_track_impl.h" |
| 11 |
| 12 namespace mojo { |
| 13 namespace media { |
| 14 namespace audio { |
| 15 |
| 16 AudioPipe::AudioPacketRef::AudioPacketRef( |
| 17 MediaPacketStatePtr state, |
| 18 AudioServerImpl* server, |
| 19 std::vector<Region>&& regions, // NOLINT(build/c++11) |
| 20 int64_t start_pts, |
| 21 int64_t end_pts) |
| 22 : state_(std::move(state)), |
| 23 server_(server), |
| 24 regions_(std::move(regions)), |
| 25 start_pts_(start_pts), |
| 26 end_pts_(end_pts) { |
| 27 DCHECK(state_); |
| 28 DCHECK(server_); |
| 29 } |
| 30 |
| 31 AudioPipe::AudioPacketRef::~AudioPacketRef() { |
| 32 DCHECK(server_); |
| 33 server_->SchedulePacketCleanup(std::move(state_)); |
| 34 } |
| 35 |
| 36 AudioPipe::AudioPipe(AudioTrackImpl* owner, |
| 37 AudioServerImpl* server) |
| 38 : owner_(owner), |
| 39 server_(server) { |
| 40 DCHECK(owner_); |
| 41 DCHECK(server_); |
| 42 } |
| 43 |
| 44 AudioPipe::~AudioPipe() {} |
| 45 |
| 46 void AudioPipe::OnPacketReceived(MediaPacketStatePtr state) { |
| 47 const MediaPacketPtr& packet = state->GetPacket(); |
| 48 DCHECK(packet); |
| 49 DCHECK(packet->payload); |
| 50 DCHECK(owner_); |
| 51 |
| 52 // Start by making sure that we are regions we are receiving are made from an |
| 53 // integral number of audio frames. Count the total number of frames in the |
| 54 // process. |
| 55 // |
| 56 // TODO(johngro): Someday, automatically enforce this using |
| 57 // alignment/allocation restrictions at the MediaPipe level of things. |
| 58 uint32_t frame_count = 0; |
| 59 uint32_t frame_size = owner_->BytesPerFrame(); |
| 60 const MediaPacketRegionPtr* region = &packet->payload; |
| 61 size_t ndx = 0; |
| 62 std::vector<AudioPacketRef::Region> regions; |
| 63 |
| 64 regions.reserve(packet->extra_payload.size() + 1); |
| 65 |
| 66 DCHECK(frame_size); |
| 67 while (true) { |
| 68 if ((frame_size > 1) && ((*region)->length % frame_size)) { |
| 69 state->SetResult(MediaResult::INVALID_ARGUMENT); |
| 70 return; |
| 71 } |
| 72 |
| 73 frame_count += ((*region)->length / frame_size); |
| 74 if (frame_count > (std::numeric_limits<uint32_t>::max() >> |
| 75 AudioTrackImpl::PTS_FRACTIONAL_BITS)) { |
| 76 state->SetResult(MediaResult::INVALID_ARGUMENT); |
| 77 return; |
| 78 } |
| 79 |
| 80 regions.emplace_back( |
| 81 static_cast<const uint8_t*>(buffer()) + (*region)->offset, |
| 82 frame_count << AudioTrackImpl::PTS_FRACTIONAL_BITS); |
| 83 |
| 84 if (ndx >= packet->extra_payload.size()) { |
| 85 break; |
| 86 } |
| 87 |
| 88 region = &(packet->extra_payload[ndx]); |
| 89 ndx++; |
| 90 } |
| 91 |
| 92 // Figure out the starting PTS. |
| 93 int64_t start_pts; |
| 94 if (packet->pts != MediaPacket::kNoTimestamp) { |
| 95 // The user provided an explicit PTS for this audio. Transform it into |
| 96 // units of fractional frames. |
| 97 LinearTransform tmp(0, owner_->FractionalFrameToMediaTimeRatio(), 0); |
| 98 if (!tmp.DoForwardTransform(packet->pts, &start_pts)) { |
| 99 state->SetResult(MediaResult::INTERNAL_ERROR); |
| 100 return; |
| 101 } |
| 102 } else { |
| 103 // No PTS was provided. Use the end time of the last audio packet, if |
| 104 // known. Otherwise, just assume a media time of 0. |
| 105 start_pts = next_pts_known_ ? next_pts_ : 0; |
| 106 } |
| 107 |
| 108 // The end pts is the value we will use for the next packet's start PTS, if |
| 109 // the user does not provide an explicit PTS. |
| 110 int64_t pts_delta = (static_cast<int64_t>(frame_count) |
| 111 << AudioTrackImpl::PTS_FRACTIONAL_BITS); |
| 112 next_pts_ = start_pts + pts_delta; |
| 113 next_pts_known_ = true; |
| 114 |
| 115 owner_->OnPacketReceived(AudioPacketRefPtr( |
| 116 new AudioPacketRef(std::move(state), |
| 117 server_, |
| 118 std::move(regions), |
| 119 start_pts, |
| 120 next_pts_))); |
| 121 } |
| 122 |
| 123 void AudioPipe::OnFlushRequested(const FlushCallback& cbk) { |
| 124 DCHECK(owner_); |
| 125 owner_->OnFlushRequested(cbk); |
| 126 next_pts_known_ = false; |
| 127 } |
| 128 |
| 129 } // namespace audio |
| 130 } // namespace media |
| 131 } // namespace mojo |
OLD | NEW |