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