1 // Copyright 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.
5 #include "content/renderer/media/audio_decoder.h"
9 #include "base/basictypes.h"
10 #include "base/strings/string_util.h"
11 #include "base/time/time.h"
12 #include "media/base/audio_bus.h"
13 #include "media/base/limits.h"
14 #include "media/filters/audio_file_reader.h"
15 #include "media/filters/in_memory_url_protocol.h"
16 #include "third_party/WebKit/public/platform/WebAudioBus.h"
18 using media::AudioBus
;
19 using media::AudioFileReader
;
20 using media::InMemoryUrlProtocol
;
22 using blink::WebAudioBus
;
26 // Decode in-memory audio file data.
27 bool DecodeAudioFileData(
28 blink::WebAudioBus
* destination_bus
,
29 const char* data
, size_t data_size
) {
30 DCHECK(destination_bus
);
34 // Uses the FFmpeg library for audio file reading.
35 InMemoryUrlProtocol
url_protocol(reinterpret_cast<const uint8
*>(data
),
37 AudioFileReader
reader(&url_protocol
);
42 size_t number_of_channels
= reader
.channels();
43 double file_sample_rate
= reader
.sample_rate();
44 size_t number_of_frames
= static_cast<size_t>(reader
.GetNumberOfFrames());
46 // Apply sanity checks to make sure crazy values aren't coming out of
48 if (!number_of_channels
||
49 number_of_channels
> static_cast<size_t>(media::limits::kMaxChannels
) ||
50 file_sample_rate
< media::limits::kMinSampleRate
||
51 file_sample_rate
> media::limits::kMaxSampleRate
)
54 // Allocate and configure the output audio channel data.
55 destination_bus
->initialize(number_of_channels
,
59 // Wrap the channel pointers which will receive the decoded PCM audio.
60 vector
<float*> audio_data
;
61 audio_data
.reserve(number_of_channels
);
62 for (size_t i
= 0; i
< number_of_channels
; ++i
) {
63 audio_data
.push_back(destination_bus
->channelData(i
));
66 scoped_ptr
<AudioBus
> audio_bus
= AudioBus::WrapVector(
67 number_of_frames
, audio_data
);
69 // Decode the audio file data.
70 // TODO(crogers): If our estimate was low, then we still may fail to read
71 // all of the data from the file.
72 size_t actual_frames
= reader
.Read(audio_bus
.get());
74 // Adjust WebKit's bus to account for the actual file length
75 // and valid data read.
76 if (actual_frames
!= number_of_frames
) {
77 DCHECK_LE(actual_frames
, number_of_frames
);
78 destination_bus
->resizeSmaller(actual_frames
);
81 double duration
= actual_frames
/ file_sample_rate
;
83 DVLOG(1) << "Decoded file data -"
85 << " data size: " << data_size
86 << " duration: " << duration
87 << " number of frames: " << actual_frames
88 << " sample rate: " << file_sample_rate
89 << " number of channels: " << number_of_channels
;
91 return actual_frames
> 0;
94 } // namespace content