1 // Copyright 2014 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 "media/formats/webm/webm_audio_client.h" 6 7 #include "media/base/audio_decoder_config.h" 8 #include "media/base/channel_layout.h" 9 #include "media/formats/webm/webm_constants.h" 10 11 namespace media { 12 13 WebMAudioClient::WebMAudioClient(const LogCB& log_cb) 14 : log_cb_(log_cb) { 15 Reset(); 16 } 17 18 WebMAudioClient::~WebMAudioClient() { 19 } 20 21 void WebMAudioClient::Reset() { 22 channels_ = -1; 23 samples_per_second_ = -1; 24 output_samples_per_second_ = -1; 25 } 26 27 bool WebMAudioClient::InitializeConfig( 28 const std::string& codec_id, const std::vector<uint8>& codec_private, 29 int64 seek_preroll, int64 codec_delay, bool is_encrypted, 30 AudioDecoderConfig* config) { 31 DCHECK(config); 32 SampleFormat sample_format = kSampleFormatPlanarF32; 33 34 AudioCodec audio_codec = kUnknownAudioCodec; 35 if (codec_id == "A_VORBIS") { 36 audio_codec = kCodecVorbis; 37 } else if (codec_id == "A_OPUS") { 38 audio_codec = kCodecOpus; 39 } else { 40 MEDIA_LOG(log_cb_) << "Unsupported audio codec_id " << codec_id; 41 return false; 42 } 43 44 if (samples_per_second_ <= 0) 45 return false; 46 47 // Set channel layout default if a Channels element was not present. 48 if (channels_ == -1) 49 channels_ = 1; 50 51 ChannelLayout channel_layout = GuessChannelLayout(channels_); 52 53 if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) { 54 MEDIA_LOG(log_cb_) << "Unsupported channel count " << channels_; 55 return false; 56 } 57 58 int samples_per_second = samples_per_second_; 59 if (output_samples_per_second_ > 0) 60 samples_per_second = output_samples_per_second_; 61 62 // Always use 48kHz for OPUS. See the "Input Sample Rate" section of the 63 // spec: http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11 64 if (audio_codec == kCodecOpus) { 65 samples_per_second = 48000; 66 sample_format = kSampleFormatF32; 67 } 68 69 const uint8* extra_data = NULL; 70 size_t extra_data_size = 0; 71 if (codec_private.size() > 0) { 72 extra_data = &codec_private[0]; 73 extra_data_size = codec_private.size(); 74 } 75 76 // Convert |codec_delay| from nanoseconds into frames. 77 int codec_delay_in_frames = 0; 78 if (codec_delay != -1) { 79 codec_delay_in_frames = 80 0.5 + 81 samples_per_second * (static_cast<double>(codec_delay) / 82 base::Time::kNanosecondsPerSecond); 83 } 84 85 config->Initialize( 86 audio_codec, 87 sample_format, 88 channel_layout, 89 samples_per_second, 90 extra_data, 91 extra_data_size, 92 is_encrypted, 93 true, 94 base::TimeDelta::FromMicroseconds( 95 (seek_preroll != -1 ? seek_preroll : 0) / 1000), 96 codec_delay_in_frames); 97 return config->IsValidConfig(); 98 } 99 100 bool WebMAudioClient::OnUInt(int id, int64 val) { 101 if (id == kWebMIdChannels) { 102 if (channels_ != -1) { 103 MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id 104 << " specified. (" << channels_ << " and " << val 105 << ")"; 106 return false; 107 } 108 109 channels_ = val; 110 } 111 return true; 112 } 113 114 bool WebMAudioClient::OnFloat(int id, double val) { 115 double* dst = NULL; 116 117 switch (id) { 118 case kWebMIdSamplingFrequency: 119 dst = &samples_per_second_; 120 break; 121 case kWebMIdOutputSamplingFrequency: 122 dst = &output_samples_per_second_; 123 break; 124 default: 125 return true; 126 } 127 128 if (val <= 0) 129 return false; 130 131 if (*dst != -1) { 132 MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id 133 << " specified (" << *dst << " and " << val << ")"; 134 return false; 135 } 136 137 *dst = val; 138 return true; 139 } 140 141 } // namespace media 142