Shaka Player Embedded
audio_renderer_common.cc
Go to the documentation of this file.
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #include <algorithm>
18 #include <cstring>
19 #include <functional>
20 #include <vector>
21 
22 namespace shaka {
23 namespace media {
24 
25 namespace {
26 
28 const double kBufferTarget = 2;
29 
31 const double kSyncLimit = 0.1;
32 
34 const uint8_t kSilenceBuffer[4096] = {0};
35 
36 
37 uint8_t BytesPerSample(std::shared_ptr<DecodedFrame> frame) {
38  switch (get<SampleFormat>(frame->format)) {
41  return 1;
44  return 2;
47  return 4;
50  return 8;
53  return 4;
56  return 8;
57  default:
58  LOG(DFATAL) << "Unsupported sample format: " << frame->format;
59  return 0;
60  }
61 }
62 
63 size_t BytesToSamples(std::shared_ptr<DecodedFrame> frame, size_t bytes) {
64  size_t bytes_per_sample =
65  BytesPerSample(frame) * frame->stream_info->channel_count;
66  CHECK_EQ(bytes % bytes_per_sample, 0);
67  return bytes / bytes_per_sample;
68 }
69 
70 double BytesToSeconds(std::shared_ptr<DecodedFrame> frame, size_t bytes) {
71  return static_cast<double>(BytesToSamples(frame, bytes)) /
72  frame->stream_info->sample_rate;
73 }
74 
84 int64_t GetSyncBytes(double prev_time, size_t bytes_written,
85  std::shared_ptr<DecodedFrame> next) {
86  const int64_t bytes_per_sample = BytesPerSample(next);
87  const double buffer_end = prev_time + BytesToSeconds(next, bytes_written);
88  // If the difference is small, just ignore for now.
89  if (std::abs(buffer_end - next->pts) < kSyncLimit)
90  return 0;
91 
92  // Round to whole samples before converting to bytes.
93  const int64_t sample_delta = static_cast<int64_t>(
94  (buffer_end - next->pts) * next->stream_info->sample_rate);
95  return sample_delta * next->stream_info->channel_count * bytes_per_sample;
96 }
97 
98 } // namespace
99 
101  : mutex_("AudioRendererCommon"),
102  on_play_("AudioRendererCommon"),
103  clock_(&util::Clock::Instance),
104  player_(nullptr),
105  input_(nullptr),
106  volume_(1),
107  muted_(false),
108  needs_resync_(true),
109  shutdown_(false),
110  thread_("AudioRenderer",
111  std::bind(&AudioRendererCommon::ThreadMain, this)) {}
112 
114  CHECK(shutdown_) << "Must call Stop before destroying";
115  thread_.join();
116  if (player_)
117  player_->RemoveClient(this);
118 }
119 
121  std::unique_lock<Mutex> lock(mutex_);
122  if (player_)
123  player_->RemoveClient(this);
124 
125  player_ = player;
126  needs_resync_ = true;
127  if (player) {
128  player->AddClient(this);
129  on_play_.SignalAllIfNotSet();
130  }
131 }
132 
134  std::unique_lock<Mutex> lock(mutex_);
135  input_ = stream;
136  needs_resync_ = true;
137  if (stream)
138  on_play_.SignalAllIfNotSet();
139 }
140 
142  std::unique_lock<Mutex> lock(mutex_);
143  input_ = nullptr;
144  SetDeviceState(/* is_playing= */ false);
145 }
146 
148  std::unique_lock<Mutex> lock(mutex_);
149  return volume_;
150 }
151 
152 void AudioRendererCommon::SetVolume(double volume) {
153  std::unique_lock<Mutex> lock(mutex_);
154  volume_ = volume;
155  UpdateVolume(muted_ ? 0 : volume_);
156 }
157 
159  std::unique_lock<Mutex> lock(mutex_);
160  return muted_;
161 }
162 
164  std::unique_lock<Mutex> lock(mutex_);
165  muted_ = muted;
166  UpdateVolume(muted ? 0 : volume_);
167 }
168 
170  {
171  std::unique_lock<Mutex> lock(mutex_);
172  shutdown_ = true;
173  }
174  on_play_.SignalAllIfNotSet();
175 }
176 
177 bool AudioRendererCommon::FillSilence(size_t bytes) {
178  while (bytes > 0) {
179  const size_t to_write = std::min(bytes, sizeof(kSilenceBuffer));
180  if (!AppendBuffer(kSilenceBuffer, to_write))
181  return false;
182  bytes_written_ += to_write;
183  bytes -= to_write;
184  }
185  return true;
186 }
187 
188 bool AudioRendererCommon::IsFrameSimilar(
189  std::shared_ptr<DecodedFrame> frame1,
190  std::shared_ptr<DecodedFrame> frame2) const {
191  return frame1 && frame2 && frame1->stream_info == frame2->stream_info &&
192  frame1->format == frame2->format;
193 }
194 
195 bool AudioRendererCommon::WriteFrame(std::shared_ptr<DecodedFrame> frame,
196  size_t sync_bytes) {
197  if (IsPlanarFormat(frame->format)) {
198  // We need to pack the samples into a single array.
199  // Before:
200  // data[0] -> | 1A | 1B | 1C |
201  // data[1] -> | 2A | 2B | 2C |
202  // After:
203  // data -> | 1A | 2A | 1B | 2B | 1C | 2C |
204  const size_t channel_count = frame->stream_info->channel_count;
205  const size_t sample_size = BytesPerSample(frame);
206  const size_t sample_count = frame->linesize[0] / sample_size;
207  const size_t per_channel_sync = sync_bytes / channel_count;
208  const size_t skipped_samples = per_channel_sync / sample_size;
209  if (sample_count > skipped_samples) {
210  std::vector<uint8_t> temp(frame->linesize[0] * channel_count -
211  sync_bytes);
212  uint8_t* output = temp.data();
213  for (size_t sample = skipped_samples; sample < sample_count; sample++) {
214  for (size_t channel = 0; channel < channel_count; channel++) {
215  std::memcpy(output, frame->data[channel] + sample * sample_size,
216  sample_size);
217  output += sample_size;
218  }
219  }
220  if (!AppendBuffer(temp.data(), temp.size()))
221  return false;
222  bytes_written_ += temp.size();
223  }
224  } else {
225  if (frame->linesize[0] > sync_bytes) {
226  if (!AppendBuffer(frame->data[0] + sync_bytes,
227  frame->linesize[0] - sync_bytes)) {
228  return false;
229  }
230  bytes_written_ += frame->linesize[0] - sync_bytes;
231  }
232  }
233  return true;
234 }
235 
236 void AudioRendererCommon::SetClock(const util::Clock* clock) {
237  clock_ = clock;
238 }
239 
240 void AudioRendererCommon::ThreadMain() {
241  std::unique_lock<Mutex> lock(mutex_);
242  while (!shutdown_) {
243  if (!player_ || !input_) {
244  on_play_.ResetAndWaitWhileUnlocked(lock);
245  continue;
246  }
247 
248  // TODO(#15): Support playback rate. For the moment, mute audio.
249  const bool is_playing =
250  player_->PlaybackRate() == 1 &&
252  SetDeviceState(is_playing);
253  if (!is_playing) {
254  on_play_.ResetAndWaitWhileUnlocked(lock);
255  continue;
256  }
257 
258  double time = player_->CurrentTime();
259  const size_t buffered_bytes = GetBytesBuffered();
260  std::shared_ptr<DecodedFrame> next;
261  if (needs_resync_ || !cur_frame_) {
262  ClearBuffer();
263  next = input_->GetFrame(time, FrameLocation::Near);
264  } else {
265  const double buffered_extra =
266  BytesToSeconds(cur_frame_, buffered_bytes) - kBufferTarget;
267  if (buffered_extra > 0) {
268  util::Unlocker<Mutex> unlock(&lock);
269  clock_->SleepSeconds(buffered_extra);
270  continue;
271  }
272 
273  next = input_->GetFrame(cur_frame_->pts, FrameLocation::After);
274  }
275 
276  if (!next) {
277  util::Unlocker<Mutex> unlock(&lock);
278  clock_->SleepSeconds(0.1);
279  continue;
280  }
281 
282  if (!IsFrameSimilar(cur_frame_, next)) {
283  // If we've changed to another stream, reset the audio device to the new
284  // stream.
285  if (cur_frame_) {
286  // Try to play out the existing buffer since resetting will clear the
287  // buffer.
288  const double buffered = BytesToSeconds(cur_frame_, buffered_bytes);
289  const double delay = std::max(buffered - 0.1, 0.0);
290  util::Unlocker<Mutex> unlock(&lock);
291  clock_->SleepSeconds(delay);
292  if (shutdown_)
293  return;
294  time = player_->CurrentTime();
295  }
296 
297  if (!InitDevice(next, muted_ ? 0 : volume_))
298  return;
299  SetDeviceState(/* is_playing= */ true);
300  needs_resync_ = true;
301  }
302 
303  int64_t sync_bytes;
304  if (needs_resync_ || !cur_frame_) {
305  sync_bytes = GetSyncBytes(time, 0, next);
306  sync_time_ = time;
307  bytes_written_ = 0;
308  } else {
309  sync_bytes = GetSyncBytes(sync_time_, bytes_written_, next);
310  }
311  if (sync_bytes < 0) {
312  if (!FillSilence(-sync_bytes))
313  return;
314  sync_bytes = 0;
315  }
316  if (!WriteFrame(next, sync_bytes))
317  return;
318  cur_frame_ = next;
319  needs_resync_ = false;
320  }
321 }
322 
323 void AudioRendererCommon::OnPlaybackStateChanged(VideoPlaybackState old_state,
324  VideoPlaybackState new_state) {
325  std::unique_lock<Mutex> lock(mutex_);
326  needs_resync_ = true;
327  on_play_.SignalAllIfNotSet();
328 }
329 
330 void AudioRendererCommon::OnPlaybackRateChanged(double old_rate,
331  double new_rate) {
332  std::unique_lock<Mutex> lock(mutex_);
333  needs_resync_ = true;
334  on_play_.SignalAllIfNotSet();
335 }
336 
337 void AudioRendererCommon::OnSeeking() {
338  std::unique_lock<Mutex> lock(mutex_);
339  needs_resync_ = true;
340  on_play_.SignalAllIfNotSet();
341 }
342 
343 } // namespace media
344 } // namespace shaka
void SetPlayer(const MediaPlayer *player) override
virtual VideoPlaybackState PlaybackState() const =0
virtual void AddClient(Client *client) const =0
std::shared_ptr< shaka::media::DecodedFrame > frame
void join()
Definition: thread.h:56
virtual void RemoveClient(Client *client) const =0
virtual double PlaybackRate() const =0
bool IsPlanarFormat(variant< PixelFormat, SampleFormat > format)
Definition: frames.cc:68
void SetVolume(double volume) override
T ResetAndWaitWhileUnlocked(std::unique_lock< _Mutex > &lock)
Definition: thread_event.h:106
virtual double CurrentTime() const =0
virtual void SleepSeconds(double seconds) const
Definition: clock.cc:39
std::shared_ptr< T > GetFrame(double time, FrameLocation kind=FrameLocation::After) const
Definition: streams.h:192
void Attach(const DecodedStream *stream) override