summaryrefslogtreecommitdiff
path: root/media/formats/webm/webm_audio_client.cc
blob: 92bb40f0ace1be47ed4d346c628e41c4d5702cb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 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(const LogCB& log_cb)
    : log_cb_(log_cb) {
  Reset();
}

WebMAudioClient::~WebMAudioClient() {
}

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>& codec_private,
    int64 seek_preroll, int64 codec_delay, bool is_encrypted,
    AudioDecoderConfig* config) {
  DCHECK(config);
  SampleFormat sample_format = kSampleFormatPlanarF32;

  AudioCodec audio_codec = kUnknownAudioCodec;
  if (codec_id == "A_VORBIS") {
    audio_codec = kCodecVorbis;
  } else if (codec_id == "A_OPUS") {
    audio_codec = kCodecOpus;
  } else {
    MEDIA_LOG(log_cb_) << "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 =  GuessChannelLayout(channels_);

  if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
    MEDIA_LOG(log_cb_) << "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 == kCodecOpus) {
    samples_per_second = 48000;
    sample_format = kSampleFormatF32;
  }

  const uint8* extra_data = NULL;
  size_t extra_data_size = 0;
  if (codec_private.size() > 0) {
    extra_data = &codec_private[0];
    extra_data_size = codec_private.size();
  }

  // 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,
      extra_data,
      extra_data_size,
      is_encrypted,
      true,
      base::TimeDelta::FromMicroseconds(
          (seek_preroll != -1 ? seek_preroll : 0) / 1000),
      codec_delay_in_frames);
  return config->IsValidConfig();
}

bool WebMAudioClient::OnUInt(int id, int64 val) {
  if (id == kWebMIdChannels) {
    if (channels_ != -1) {
      MEDIA_LOG(log_cb_) << "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(log_cb_) << "Multiple values for id " << std::hex << id
                       << " specified (" << *dst << " and " << val << ")";
    return false;
  }

  *dst = val;
  return true;
}

}  // namespace media