| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <limits> | 6 #include <limits> |
| 7 | 7 |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "mojo/services/media/common/cpp/linear_transform.h" | 9 #include "mojo/services/media/common/cpp/linear_transform.h" |
| 10 #include "services/media/audio/audio_output_manager.h" | 10 #include "services/media/audio/audio_output_manager.h" |
| 11 #include "services/media/audio/audio_server_impl.h" | 11 #include "services/media/audio/audio_server_impl.h" |
| 12 #include "services/media/audio/audio_track_impl.h" | 12 #include "services/media/audio/audio_track_impl.h" |
| 13 #include "services/media/audio/audio_track_to_output_link.h" | 13 #include "services/media/audio/audio_track_to_output_link.h" |
| 14 | 14 |
| 15 namespace mojo { | 15 namespace mojo { |
| 16 namespace media { | 16 namespace media { |
| 17 namespace audio { | 17 namespace audio { |
| 18 | 18 |
| 19 constexpr size_t AudioTrackImpl::PTS_FRACTIONAL_BITS; | 19 constexpr size_t AudioTrackImpl::PTS_FRACTIONAL_BITS; |
| 20 | 20 |
| 21 // TODO(johngro): If there is ever a better way to do this type of static-table | 21 // TODO(johngro): If there is ever a better way to do this type of static-table |
| 22 // initialization using mojom generated structs, we should switch to it. | 22 // initialization using mojom generated structs, we should switch to it. |
| 23 static const struct { | 23 static const struct { |
| 24 LpcmSampleFormat sample_format; | 24 AudioSampleFormat sample_format; |
| 25 uint32_t min_channels; | 25 uint32_t min_channels; |
| 26 uint32_t max_channels; | 26 uint32_t max_channels; |
| 27 uint32_t min_frames_per_second; | 27 uint32_t min_frames_per_second; |
| 28 uint32_t max_frames_per_second; | 28 uint32_t max_frames_per_second; |
| 29 } kSupportedLpcmTypeSets[] = { | 29 } kSupportedAudioTypeSets[] = { |
| 30 { | 30 { |
| 31 .sample_format = LpcmSampleFormat::UNSIGNED_8, | 31 .sample_format = AudioSampleFormat::UNSIGNED_8, |
| 32 .min_channels = 1, | 32 .min_channels = 1, |
| 33 .max_channels = 2, | 33 .max_channels = 2, |
| 34 .min_frames_per_second = 1000, | 34 .min_frames_per_second = 1000, |
| 35 .max_frames_per_second = 48000, | 35 .max_frames_per_second = 48000, |
| 36 }, | 36 }, |
| 37 { | 37 { |
| 38 .sample_format = LpcmSampleFormat::SIGNED_16, | 38 .sample_format = AudioSampleFormat::SIGNED_16, |
| 39 .min_channels = 1, | 39 .min_channels = 1, |
| 40 .max_channels = 2, | 40 .max_channels = 2, |
| 41 .min_frames_per_second = 1000, | 41 .min_frames_per_second = 1000, |
| 42 .max_frames_per_second = 48000, | 42 .max_frames_per_second = 48000, |
| 43 }, | 43 }, |
| 44 }; | 44 }; |
| 45 | 45 |
| 46 AudioTrackImpl::AudioTrackImpl(InterfaceRequest<AudioTrack> iface, | 46 AudioTrackImpl::AudioTrackImpl(InterfaceRequest<AudioTrack> iface, |
| 47 AudioServerImpl* owner) | 47 AudioServerImpl* owner) |
| 48 : owner_(owner), | 48 : owner_(owner), |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 // compiled with. | 101 // compiled with. |
| 102 // | 102 // |
| 103 // For now, it would be nice to just be able to have a static const tree of | 103 // For now, it would be nice to just be able to have a static const tree of |
| 104 // capabilities in this translational unit which we could use to construct our | 104 // capabilities in this translational unit which we could use to construct our |
| 105 // message, but the nature of the structures generated by the C++ bindings | 105 // message, but the nature of the structures generated by the C++ bindings |
| 106 // make this difficult. For now, we just create a trivial descriptor entierly | 106 // make this difficult. For now, we just create a trivial descriptor entierly |
| 107 // by hand. | 107 // by hand. |
| 108 AudioTrackDescriptorPtr desc(AudioTrackDescriptor::New()); | 108 AudioTrackDescriptorPtr desc(AudioTrackDescriptor::New()); |
| 109 | 109 |
| 110 desc->supported_media_types = | 110 desc->supported_media_types = |
| 111 Array<MediaTypeSetPtr>::New(arraysize(kSupportedLpcmTypeSets)); | 111 Array<MediaTypeSetPtr>::New(arraysize(kSupportedAudioTypeSets)); |
| 112 | 112 |
| 113 for (size_t i = 0; i < desc->supported_media_types.size(); ++i) { | 113 for (size_t i = 0; i < desc->supported_media_types.size(); ++i) { |
| 114 const MediaTypeSetPtr& mts = | 114 const MediaTypeSetPtr& mts = |
| 115 (desc->supported_media_types[i] = MediaTypeSet::New()); | 115 (desc->supported_media_types[i] = MediaTypeSet::New()); |
| 116 | 116 |
| 117 mts->scheme = MediaTypeScheme::LPCM; | 117 mts->medium = MediaTypeMedium::AUDIO; |
| 118 mts->details = MediaTypeSetDetails::New(); | 118 mts->encodings = Array<String>::New(1); |
| 119 mts->details = MediaTypeSetDetails::New(); |
| 119 | 120 |
| 120 const auto& s = kSupportedLpcmTypeSets[i]; | 121 mts->encodings[0] = MediaType::kAudioEncodingLpcm; |
| 121 LpcmMediaTypeSetDetailsPtr lpcm_detail = LpcmMediaTypeSetDetails::New(); | |
| 122 | 122 |
| 123 lpcm_detail->sample_format = s.sample_format; | 123 const auto& s = kSupportedAudioTypeSets[i]; |
| 124 lpcm_detail->min_channels = s.min_channels; | 124 AudioMediaTypeSetDetailsPtr audio_detail = AudioMediaTypeSetDetails::New(); |
| 125 lpcm_detail->max_channels = s.max_channels; | 125 |
| 126 lpcm_detail->min_frames_per_second = s.min_frames_per_second; | 126 audio_detail->sample_format = s.sample_format; |
| 127 lpcm_detail->max_frames_per_second = s.max_frames_per_second; | 127 audio_detail->min_channels = s.min_channels; |
| 128 mts->details->set_lpcm(lpcm_detail.Pass()); | 128 audio_detail->max_channels = s.max_channels; |
| 129 audio_detail->min_frames_per_second = s.min_frames_per_second; |
| 130 audio_detail->max_frames_per_second = s.max_frames_per_second; |
| 131 mts->details->set_audio(audio_detail.Pass()); |
| 129 } | 132 } |
| 130 | 133 |
| 131 cbk.Run(desc.Pass()); | 134 cbk.Run(desc.Pass()); |
| 132 } | 135 } |
| 133 | 136 |
| 134 void AudioTrackImpl::Configure(AudioTrackConfigurationPtr configuration, | 137 void AudioTrackImpl::Configure(AudioTrackConfigurationPtr configuration, |
| 135 InterfaceRequest<MediaConsumer> req) { | 138 InterfaceRequest<MediaConsumer> req) { |
| 136 // Are we already configured? | 139 // Are we already configured? |
| 137 if (pipe_.IsInitialized()) { | 140 if (pipe_.IsInitialized()) { |
| 138 LOG(ERROR) << "Attempting to reconfigure a configured audio track."; | 141 LOG(ERROR) << "Attempting to reconfigure a configured audio track."; |
| 139 Shutdown(); | 142 Shutdown(); |
| 140 return; | 143 return; |
| 141 } | 144 } |
| 142 | 145 |
| 143 // Check the requested configuration. | 146 // Check the requested configuration. |
| 144 if ((configuration->media_type->scheme != MediaTypeScheme::LPCM) || | 147 if ((configuration->media_type->medium != MediaTypeMedium::AUDIO) || |
| 145 (!configuration->media_type->details->is_lpcm())) { | 148 (configuration->media_type->encoding != MediaType::kAudioEncodingLpcm) || |
| 149 (!configuration->media_type->details->is_audio())) { |
| 146 LOG(ERROR) << "Unsupported configuration requested in " | 150 LOG(ERROR) << "Unsupported configuration requested in " |
| 147 "AudioTrack::Configure. Media type must be LPCM."; | 151 "AudioTrack::Configure. Media type must be LPCM audio."; |
| 148 Shutdown(); | 152 Shutdown(); |
| 149 return; | 153 return; |
| 150 } | 154 } |
| 151 | 155 |
| 152 // Search our supported configuration sets to find one compatible with this | 156 // Search our supported configuration sets to find one compatible with this |
| 153 // request. | 157 // request. |
| 154 auto& cfg = configuration->media_type->details->get_lpcm(); | 158 auto& cfg = configuration->media_type->details->get_audio(); |
| 155 size_t i; | 159 size_t i; |
| 156 for (i = 0; i < arraysize(kSupportedLpcmTypeSets); ++i) { | 160 for (i = 0; i < arraysize(kSupportedAudioTypeSets); ++i) { |
| 157 const auto& cfg_set = kSupportedLpcmTypeSets[i]; | 161 const auto& cfg_set = kSupportedAudioTypeSets[i]; |
| 158 | 162 |
| 159 if ((cfg->sample_format == cfg_set.sample_format) && | 163 if ((cfg->sample_format == cfg_set.sample_format) && |
| 160 (cfg->channels >= cfg_set.min_channels) && | 164 (cfg->channels >= cfg_set.min_channels) && |
| 161 (cfg->channels <= cfg_set.max_channels) && | 165 (cfg->channels <= cfg_set.max_channels) && |
| 162 (cfg->frames_per_second >= cfg_set.min_frames_per_second) && | 166 (cfg->frames_per_second >= cfg_set.min_frames_per_second) && |
| 163 (cfg->frames_per_second <= cfg_set.max_frames_per_second)) { | 167 (cfg->frames_per_second <= cfg_set.max_frames_per_second)) { |
| 164 break; | 168 break; |
| 165 } | 169 } |
| 166 } | 170 } |
| 167 | 171 |
| 168 if (i >= arraysize(kSupportedLpcmTypeSets)) { | 172 if (i >= arraysize(kSupportedAudioTypeSets)) { |
| 169 LOG(ERROR) << "Unsupported LPCM configuration requested in " | 173 LOG(ERROR) << "Unsupported LPCM configuration requested in " |
| 170 "AudioTrack::Configure. " | 174 "AudioTrack::Configure. " |
| 171 << "(format = " << cfg->sample_format | 175 << "(format = " << cfg->sample_format |
| 172 << ", channels = " | 176 << ", channels = " |
| 173 << static_cast<uint32_t>(cfg->channels) | 177 << static_cast<uint32_t>(cfg->channels) |
| 174 << ", frames_per_second = " << cfg->frames_per_second | 178 << ", frames_per_second = " << cfg->frames_per_second |
| 175 << ")"; | 179 << ")"; |
| 176 Shutdown(); | 180 Shutdown(); |
| 177 return; | 181 return; |
| 178 } | 182 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 199 if (!no_loss) { | 203 if (!no_loss) { |
| 200 LOG(ERROR) << "Invalid (audio frames:media time ticks) ratio (" | 204 LOG(ERROR) << "Invalid (audio frames:media time ticks) ratio (" |
| 201 << numerator << "/" << denominator << ")"; | 205 << numerator << "/" << denominator << ")"; |
| 202 Shutdown(); | 206 Shutdown(); |
| 203 return; | 207 return; |
| 204 } | 208 } |
| 205 | 209 |
| 206 // Figure out how many bytes we need to hold the requested number of nSec of | 210 // Figure out how many bytes we need to hold the requested number of nSec of |
| 207 // audio. | 211 // audio. |
| 208 switch (cfg->sample_format) { | 212 switch (cfg->sample_format) { |
| 209 case LpcmSampleFormat::UNSIGNED_8: | 213 case AudioSampleFormat::UNSIGNED_8: |
| 210 bytes_per_frame_ = 1; | 214 bytes_per_frame_ = 1; |
| 211 break; | 215 break; |
| 212 | 216 |
| 213 case LpcmSampleFormat::SIGNED_16: | 217 case AudioSampleFormat::SIGNED_16: |
| 214 bytes_per_frame_ = 2; | 218 bytes_per_frame_ = 2; |
| 215 break; | 219 break; |
| 216 | 220 |
| 217 case LpcmSampleFormat::SIGNED_24_IN_32: | 221 case AudioSampleFormat::SIGNED_24_IN_32: |
| 218 bytes_per_frame_ = 4; | 222 bytes_per_frame_ = 4; |
| 219 break; | 223 break; |
| 220 | 224 |
| 221 default: | 225 default: |
| 222 DCHECK(false); | 226 DCHECK(false); |
| 223 bytes_per_frame_ = 2; | 227 bytes_per_frame_ = 2; |
| 224 break; | 228 break; |
| 225 } | 229 } |
| 226 bytes_per_frame_ *= cfg->channels; | 230 bytes_per_frame_ *= cfg->channels; |
| 227 | 231 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 DCHECK(output); | 317 DCHECK(output); |
| 314 output->FlushPendingQueue(); | 318 output->FlushPendingQueue(); |
| 315 } | 319 } |
| 316 cbk.Run(); | 320 cbk.Run(); |
| 317 return true; | 321 return true; |
| 318 } | 322 } |
| 319 | 323 |
| 320 } // namespace audio | 324 } // namespace audio |
| 321 } // namespace media | 325 } // namespace media |
| 322 } // namespace mojo | 326 } // namespace mojo |
| OLD | NEW |