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 |