|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "media/formats/webm/webm_audio_client.h" | 
|  |  | 
|  | #include "media/base/audio_decoder_config.h" | 
|  | #include "media/base/channel_layout.h" | 
|  | #include "media/formats/webm/webm_constants.h" | 
|  |  | 
|  | namespace media { | 
|  |  | 
|  | WebMAudioClient::WebMAudioClient(MediaLog* media_log) : media_log_(media_log) { | 
|  | Reset(); | 
|  | } | 
|  |  | 
|  | WebMAudioClient::~WebMAudioClient() = default; | 
|  |  | 
|  | void WebMAudioClient::Reset() { | 
|  | channels_ = -1; | 
|  | samples_per_second_ = -1; | 
|  | output_samples_per_second_ = -1; | 
|  | } | 
|  |  | 
|  | bool WebMAudioClient::InitializeConfig( | 
|  | const std::string& codec_id, | 
|  | const std::vector<uint8_t>& codec_private, | 
|  | int64_t seek_preroll, | 
|  | int64_t codec_delay, | 
|  | EncryptionScheme encryption_scheme, | 
|  | AudioDecoderConfig* config) { | 
|  | DCHECK(config); | 
|  | SampleFormat sample_format = kSampleFormatPlanarF32; | 
|  |  | 
|  | AudioCodec audio_codec = AudioCodec::kUnknown; | 
|  | if (codec_id == "A_VORBIS") { | 
|  | audio_codec = AudioCodec::kVorbis; | 
|  | } else if (codec_id == "A_OPUS") { | 
|  | audio_codec = AudioCodec::kOpus; | 
|  | } else { | 
|  | MEDIA_LOG(ERROR, media_log_) << "Unsupported audio codec_id " << codec_id; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (samples_per_second_ <= 0) | 
|  | return false; | 
|  |  | 
|  | // Set channel layout default if a Channels element was not present. | 
|  | if (channels_ == -1) | 
|  | channels_ = 1; | 
|  |  | 
|  | ChannelLayout channel_layout = | 
|  | channels_ > 8 ? CHANNEL_LAYOUT_DISCRETE : GuessChannelLayout(channels_); | 
|  |  | 
|  | if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) { | 
|  | MEDIA_LOG(ERROR, media_log_) << "Unsupported channel count " << channels_; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | int samples_per_second = samples_per_second_; | 
|  | if (output_samples_per_second_ > 0) | 
|  | samples_per_second = output_samples_per_second_; | 
|  |  | 
|  | // Always use 48kHz for OPUS.  See the "Input Sample Rate" section of the | 
|  | // spec: http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11 | 
|  | if (audio_codec == AudioCodec::kOpus) { | 
|  | samples_per_second = 48000; | 
|  | sample_format = kSampleFormatF32; | 
|  | } | 
|  |  | 
|  | // Convert |codec_delay| from nanoseconds into frames. | 
|  | int codec_delay_in_frames = 0; | 
|  | if (codec_delay != -1) { | 
|  | codec_delay_in_frames = | 
|  | 0.5 + | 
|  | samples_per_second * (static_cast<double>(codec_delay) / | 
|  | base::Time::kNanosecondsPerSecond); | 
|  | } | 
|  |  | 
|  | config->Initialize( | 
|  | audio_codec, sample_format, channel_layout, samples_per_second, | 
|  | codec_private, encryption_scheme, | 
|  | base::Microseconds((seek_preroll != -1 ? seek_preroll : 0) / 1000), | 
|  | codec_delay_in_frames); | 
|  | config->SetChannelsForDiscrete(channels_); | 
|  | return config->IsValidConfig(); | 
|  | } | 
|  |  | 
|  | bool WebMAudioClient::OnUInt(int id, int64_t val) { | 
|  | if (id == kWebMIdChannels) { | 
|  | if (channels_ != -1) { | 
|  | MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex | 
|  | << id << " specified. (" << channels_ | 
|  | << " and " << val << ")"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | channels_ = val; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool WebMAudioClient::OnFloat(int id, double val) { | 
|  | double* dst = NULL; | 
|  |  | 
|  | switch (id) { | 
|  | case kWebMIdSamplingFrequency: | 
|  | dst = &samples_per_second_; | 
|  | break; | 
|  | case kWebMIdOutputSamplingFrequency: | 
|  | dst = &output_samples_per_second_; | 
|  | break; | 
|  | default: | 
|  | return true; | 
|  | } | 
|  |  | 
|  | if (val <= 0) | 
|  | return false; | 
|  |  | 
|  | if (*dst != -1) { | 
|  | MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex << id | 
|  | << " specified (" << *dst << " and " << val | 
|  | << ")"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | *dst = val; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | }  // namespace media |