1// Copyright (c) 2013 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/webm/webm_audio_client.h"
6
7#include "media/base/audio_decoder_config.h"
8#include "media/base/channel_layout.h"
9#include "media/webm/webm_constants.h"
10
11namespace media {
12
13WebMAudioClient::WebMAudioClient(const LogCB& log_cb)
14    : log_cb_(log_cb) {
15  Reset();
16}
17
18WebMAudioClient::~WebMAudioClient() {
19}
20
21void WebMAudioClient::Reset() {
22  channels_ = -1;
23  samples_per_second_ = -1;
24  output_samples_per_second_ = -1;
25}
26
27bool 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  config->Initialize(
69      audio_codec,
70      (audio_codec == kCodecOpus) ? kSampleFormatS16 : kSampleFormatPlanarF32,
71      channel_layout,
72      samples_per_second, extra_data, extra_data_size, is_encrypted, true,
73      base::TimeDelta::FromMicroseconds(
74          (seek_preroll != -1 ? seek_preroll : 0) / 1000),
75      base::TimeDelta::FromMicroseconds(
76          (codec_delay != -1 ? codec_delay : 0) / 1000));
77  return config->IsValidConfig();
78}
79
80bool WebMAudioClient::OnUInt(int id, int64 val) {
81  if (id == kWebMIdChannels) {
82    if (channels_ != -1) {
83      MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
84                         << " specified. (" << channels_ << " and " << val
85                         << ")";
86      return false;
87    }
88
89    channels_ = val;
90  }
91  return true;
92}
93
94bool WebMAudioClient::OnFloat(int id, double val) {
95  double* dst = NULL;
96
97  switch (id) {
98    case kWebMIdSamplingFrequency:
99      dst = &samples_per_second_;
100      break;
101    case kWebMIdOutputSamplingFrequency:
102      dst = &output_samples_per_second_;
103      break;
104    default:
105      return true;
106  }
107
108  if (val <= 0)
109    return false;
110
111  if (*dst != -1) {
112    MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
113                       << " specified (" << *dst << " and " << val << ")";
114    return false;
115  }
116
117  *dst = val;
118  return true;
119}
120
121}  // namespace media
122