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