blob: 0937b17a0a877f62ae448d993862139ac24d3acb [file] [log] [blame]
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "media/audio/null_audio_streamer.h"
#include <algorithm>
#include "media/audio/audio_parameters.h"
#include "media/mp4/aac.h"
namespace media {
NullAudioStreamer::NullAudioStreamer()
: null_streamer_thread_("Null Audio Streamer") {
null_streamer_thread_.Start();
null_streamer_thread_.message_loop()->PostTask(
FROM_HERE, base::Bind(&NullAudioStreamer::StartNullStreamer,
base::Unretained(this)));
}
NullAudioStreamer::~NullAudioStreamer() {
null_streamer_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&NullAudioStreamer::StopNullStreamer, base::Unretained(this)));
null_streamer_thread_.Stop();
}
ShellAudioStreamer::Config NullAudioStreamer::GetConfig() const {
// Reasonable looking settings.
const uint32 initial_rebuffering_frames_per_channel =
mp4::AAC::kFramesPerAccessUnit * 32;
const uint32 sink_buffer_size_in_frames_per_channel =
initial_rebuffering_frames_per_channel * 8;
const uint32 max_hardware_channels = 2;
return Config(Config::INTERLEAVED, initial_rebuffering_frames_per_channel,
sink_buffer_size_in_frames_per_channel, max_hardware_channels,
sizeof(float) /* bytes_per_sample */);
}
bool NullAudioStreamer::AddStream(ShellAudioStream* stream) {
base::AutoLock auto_lock(streams_lock_);
streams_.insert(std::make_pair(stream, NullAudioStream()));
return true;
}
void NullAudioStreamer::RemoveStream(ShellAudioStream* stream) {
base::AutoLock auto_lock(streams_lock_);
DLOG(INFO) << "Remove";
streams_.erase(stream);
}
bool NullAudioStreamer::HasStream(ShellAudioStream* stream) const {
base::AutoLock auto_lock(streams_lock_);
return streams_.find(stream) != streams_.end();
}
void NullAudioStreamer::StartNullStreamer() {
last_run_time_ = base::Time::Now();
advance_streams_timer_.emplace();
advance_streams_timer_->Start(
FROM_HERE, base::TimeDelta::FromMilliseconds(10),
base::Bind(&NullAudioStreamer::AdvanceStreams, base::Unretained(this)));
}
void NullAudioStreamer::StopNullStreamer() {
advance_streams_timer_->Stop();
advance_streams_timer_ = base::nullopt;
}
void NullAudioStreamer::AdvanceStreams() {
base::Time now = base::Time::Now();
base::TimeDelta time_played = now - last_run_time_;
last_run_time_ = now;
base::AutoLock auto_lock(streams_lock_);
for (NullAudioStreamMap::iterator it = streams_.begin(); it != streams_.end();
++it) {
PullFrames(it->first, time_played, &it->second);
}
}
void NullAudioStreamer::PullFrames(ShellAudioStream* stream,
base::TimeDelta time_played,
NullAudioStream* null_stream) {
// Calculate how many frames were consumed.
int sample_rate = stream->GetAudioParameters().sample_rate();
uint32 frames_played = sample_rate * time_played.InSecondsF();
frames_played = std::min(frames_played, null_stream->total_available_frames);
if (!stream->PauseRequested()) {
stream->ConsumeFrames(frames_played);
}
// Pull more frames.
stream->PullFrames(NULL, &null_stream->total_available_frames);
}
} // namespace media