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/android/audio_decoder_android.h"
14 #include "base/file_descriptor_posix.h"
15 #include "base/logging.h"
16 #include "base/memory/shared_memory.h"
17 #include "base/posix/eintr_wrapper.h"
18 #include "base/process/process_handle.h"
19 #include "content/common/view_messages.h"
20 #include "media/base/android/webaudio_media_codec_info.h"
21 #include "media/base/audio_bus.h"
22 #include "media/base/limits.h"
23 #include "third_party/WebKit/public/platform/WebAudioBus.h"
27 class AudioDecoderIO
{
29 AudioDecoderIO(const char* data
, size_t data_size
);
31 bool ShareEncodedToProcess(base::SharedMemoryHandle
* handle
);
33 // Returns true if AudioDecoderIO was successfully created.
36 int read_fd() const { return read_fd_
; }
37 int write_fd() const { return write_fd_
; }
40 // Shared memory that will hold the encoded audio data. This is
41 // used by MediaCodec for decoding.
42 base::SharedMemory encoded_shared_memory_
;
44 // A pipe used to communicate with MediaCodec. MediaCodec owns
45 // write_fd_ and writes to it.
49 DISALLOW_COPY_AND_ASSIGN(AudioDecoderIO
);
52 AudioDecoderIO::AudioDecoderIO(const char* data
, size_t data_size
)
56 if (!data
|| !data_size
|| data_size
> 0x80000000)
59 // Create the shared memory and copy our data to it so that
60 // MediaCodec can access it.
61 encoded_shared_memory_
.CreateAndMapAnonymous(data_size
);
63 if (!encoded_shared_memory_
.memory())
66 memcpy(encoded_shared_memory_
.memory(), data
, data_size
);
68 // Create a pipe for reading/writing the decoded PCM data
75 write_fd_
= pipefd
[1];
78 AudioDecoderIO::~AudioDecoderIO() {
79 // Close the read end of the pipe. The write end should have been
80 // closed by MediaCodec.
81 if (read_fd_
>= 0 && close(read_fd_
)) {
82 DVLOG(1) << "Cannot close read fd " << read_fd_
83 << ": " << strerror(errno
);
87 bool AudioDecoderIO::IsValid() const {
88 return read_fd_
>= 0 && write_fd_
>= 0 &&
89 encoded_shared_memory_
.memory();
92 bool AudioDecoderIO::ShareEncodedToProcess(base::SharedMemoryHandle
* handle
) {
93 return encoded_shared_memory_
.ShareToProcess(base::GetCurrentProcessHandle(),
97 static float ConvertSampleToFloat(int16_t sample
) {
98 const float kMaxScale
= 1.0f
/ std::numeric_limits
<int16_t>::max();
99 const float kMinScale
= -1.0f
/ std::numeric_limits
<int16_t>::min();
101 return sample
* (sample
< 0 ? kMinScale
: kMaxScale
);
104 // A basic WAVE file decoder. See
105 // https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ for a
106 // basic guide to the WAVE file format.
109 WAVEDecoder(const uint8
* data
, size_t data_size
);
112 // Try to decode the data as a WAVE file. If the data is a supported
113 // WAVE file, |destination_bus| is filled with the decoded data and
114 // DecodeWAVEFile returns true. Otherwise, DecodeWAVEFile returns
116 bool DecodeWAVEFile(blink::WebAudioBus
* destination_bus
);
119 // Minimum number of bytes in a WAVE file to hold all of the data we
120 // need to interpret it as a WAVE file.
121 static const unsigned kMinimumWAVLength
= 44;
123 // Number of bytes in the chunk ID field.
124 static const unsigned kChunkIDLength
= 4;
126 // Number of bytes in the chunk size field.
127 static const unsigned kChunkSizeLength
= 4;
129 // Number of bytes in the format field of the "RIFF" chunk.
130 static const unsigned kFormatFieldLength
= 4;
132 // Number of bytes in a valid "fmt" chunk.
133 static const unsigned kFMTChunkLength
= 16;
135 // Supported audio format in a WAVE file.
136 // TODO(rtoy): Consider supporting other formats here, if necessary.
137 static const int16_t kAudioFormatPCM
= 1;
139 // Maximum number (inclusive) of bytes per sample supported by this
141 static const unsigned kMaximumBytesPerSample
= 3;
143 // Read an unsigned integer of |length| bytes from |buffer|. The
144 // integer is interpreted as being in little-endian order.
145 uint32_t ReadUnsignedInteger(const uint8_t* buffer
, size_t length
);
147 // Read a PCM sample from the WAVE data at |pcm_data|.
148 int16_t ReadPCMSample(const uint8_t* pcm_data
);
150 // Read a WAVE chunk header including the chunk ID and chunk size.
151 // Returns false if the header could not be read.
152 bool ReadChunkHeader();
154 // Read and parse the "fmt" chunk. Returns false if the fmt chunk
155 // could not be read or contained unsupported formats.
158 // Read data chunk and save it to |destination_bus|. Returns false
159 // if the data chunk could not be read correctly.
160 bool CopyDataChunkToBus(blink::WebAudioBus
* destination_bus
);
162 // The WAVE chunk ID that identifies the chunk.
163 uint8_t chunk_id_
[kChunkIDLength
];
165 // The number of bytes in the data portion of the chunk.
168 // The total number of bytes in the encoded data.
171 // The current position within the WAVE file.
172 const uint8_t* buffer_
;
174 // Points one byte past the end of the in-memory WAVE file. Used for
175 // detecting if we've reached the end of the file.
176 const uint8_t* buffer_end_
;
178 size_t bytes_per_sample_
;
180 uint16_t number_of_channels_
;
182 // Sample rate of the WAVE data, in Hz.
183 uint32_t sample_rate_
;
185 DISALLOW_COPY_AND_ASSIGN(WAVEDecoder
);
188 WAVEDecoder::WAVEDecoder(const uint8_t* encoded_data
, size_t data_size
)
189 : data_size_(data_size
),
190 buffer_(encoded_data
),
191 buffer_end_(encoded_data
+ 1),
192 bytes_per_sample_(0),
193 number_of_channels_(0),
195 if (buffer_
+ data_size
> buffer_
)
196 buffer_end_
= buffer_
+ data_size
;
199 WAVEDecoder::~WAVEDecoder() {}
201 uint32_t WAVEDecoder::ReadUnsignedInteger(const uint8_t* buffer
,
205 if (length
== 0 || length
> sizeof(value
)) {
206 DCHECK(false) << "ReadUnsignedInteger: Invalid length: " << length
;
210 // All integer fields in a WAVE file are little-endian.
211 for (size_t k
= length
; k
> 0; --k
)
212 value
= (value
<< 8) + buffer
[k
- 1];
217 int16_t WAVEDecoder::ReadPCMSample(const uint8_t* pcm_data
) {
218 uint32_t unsigned_sample
= ReadUnsignedInteger(pcm_data
, bytes_per_sample_
);
221 // Convert the unsigned data into a 16-bit PCM sample.
222 switch (bytes_per_sample_
) {
224 sample
= (unsigned_sample
- 128) << 8;
227 sample
= static_cast<int16_t>(unsigned_sample
);
230 // Android currently converts 24-bit WAVE data into 16-bit
231 // samples by taking the high-order 16 bits without rounding.
232 // We do the same here for consistency.
233 sample
= static_cast<int16_t>(unsigned_sample
>> 8);
242 bool WAVEDecoder::ReadChunkHeader() {
243 if (buffer_
+ kChunkIDLength
+ kChunkSizeLength
>= buffer_end_
)
246 memcpy(chunk_id_
, buffer_
, kChunkIDLength
);
248 chunk_size_
= ReadUnsignedInteger(buffer_
+ kChunkIDLength
, kChunkSizeLength
);
250 // Adjust for padding
254 // Check for completely bogus chunk size.
255 if (chunk_size_
> data_size_
)
261 bool WAVEDecoder::ReadFMTChunk() {
262 // The fmt chunk has basic info about the format of the audio
263 // data. Only a basic PCM format is supported.
264 if (chunk_size_
< kFMTChunkLength
) {
265 DVLOG(1) << "FMT chunk too short: " << chunk_size_
;
269 uint16_t audio_format
= ReadUnsignedInteger(buffer_
, 2);
271 if (audio_format
!= kAudioFormatPCM
) {
272 DVLOG(1) << "Audio format not supported: " << audio_format
;
276 number_of_channels_
= ReadUnsignedInteger(buffer_
+ 2, 2);
277 sample_rate_
= ReadUnsignedInteger(buffer_
+ 4, 4);
278 unsigned bits_per_sample
= ReadUnsignedInteger(buffer_
+ 14, 2);
282 if (!number_of_channels_
||
283 number_of_channels_
> media::limits::kMaxChannels
) {
284 DVLOG(1) << "Unsupported number of channels: " << number_of_channels_
;
288 if (sample_rate_
< media::limits::kMinSampleRate
||
289 sample_rate_
> media::limits::kMaxSampleRate
) {
290 DVLOG(1) << "Unsupported sample rate: " << sample_rate_
;
294 // We only support 8, 16, and 24 bits per sample.
295 if (bits_per_sample
== 8 || bits_per_sample
== 16 || bits_per_sample
== 24) {
296 bytes_per_sample_
= bits_per_sample
/ 8;
300 DVLOG(1) << "Unsupported bits per sample: " << bits_per_sample
;
304 bool WAVEDecoder::CopyDataChunkToBus(blink::WebAudioBus
* destination_bus
) {
305 // The data chunk contains the audio data itself.
306 if (!bytes_per_sample_
|| bytes_per_sample_
> kMaximumBytesPerSample
) {
307 DVLOG(1) << "WARNING: data chunk without preceeding fmt chunk,"
308 << " or invalid bytes per sample.";
312 DVLOG(0) << "Decoding WAVE file: " << number_of_channels_
<< " channels, "
313 << sample_rate_
<< " kHz, "
314 << chunk_size_
/ bytes_per_sample_
/ number_of_channels_
315 << " frames, " << 8 * bytes_per_sample_
<< " bits/sample";
317 // Create the destination bus of the appropriate size and then decode
318 // the data into the bus.
319 size_t number_of_frames
=
320 chunk_size_
/ bytes_per_sample_
/ number_of_channels_
;
322 destination_bus
->initialize(
323 number_of_channels_
, number_of_frames
, sample_rate_
);
325 for (size_t m
= 0; m
< number_of_frames
; ++m
) {
326 for (uint16_t k
= 0; k
< number_of_channels_
; ++k
) {
327 int16_t sample
= ReadPCMSample(buffer_
);
329 buffer_
+= bytes_per_sample_
;
330 destination_bus
->channelData(k
)[m
] = ConvertSampleToFloat(sample
);
337 bool WAVEDecoder::DecodeWAVEFile(blink::WebAudioBus
* destination_bus
) {
338 // Parse and decode WAVE file. If we can't parse it, return false.
340 if (buffer_
+ kMinimumWAVLength
> buffer_end_
) {
341 DVLOG(1) << "Buffer too small to contain full WAVE header: ";
345 // Do we have a RIFF file?
347 if (memcmp(chunk_id_
, "RIFF", kChunkIDLength
) != 0) {
348 DVLOG(1) << "RIFF missing";
351 buffer_
+= kChunkIDLength
+ kChunkSizeLength
;
353 // Check the format field of the RIFF chunk
354 memcpy(chunk_id_
, buffer_
, kFormatFieldLength
);
355 if (memcmp(chunk_id_
, "WAVE", kFormatFieldLength
) != 0) {
356 DVLOG(1) << "Invalid WAVE file: missing WAVE header";
359 // Advance past the format field
360 buffer_
+= kFormatFieldLength
;
362 // We have a WAVE file. Start parsing the chunks.
364 while (buffer_
< buffer_end_
) {
365 if (!ReadChunkHeader()) {
366 DVLOG(1) << "Couldn't read chunk header";
370 // Consume the chunk ID and chunk size
371 buffer_
+= kChunkIDLength
+ kChunkSizeLength
;
373 // Make sure we can read all chunk_size bytes.
374 if (buffer_
+ chunk_size_
> buffer_end_
) {
375 DVLOG(1) << "Insufficient bytes to read chunk of size " << chunk_size_
;
379 if (memcmp(chunk_id_
, "fmt ", kChunkIDLength
) == 0) {
382 } else if (memcmp(chunk_id_
, "data", kChunkIDLength
) == 0) {
383 // Return after reading the data chunk, whether we succeeded or
385 return CopyDataChunkToBus(destination_bus
);
387 // Ignore these chunks that we don't know about.
388 DVLOG(0) << "Ignoring WAVE chunk `" << chunk_id_
<< "' size "
392 // Advance to next chunk.
393 buffer_
+= chunk_size_
;
396 // If we get here, that means we didn't find a data chunk, so we
397 // couldn't handle this WAVE file.
402 // The number of frames is known so preallocate the destination
403 // bus and copy the pcm data to the destination bus as it's being
405 static void CopyPcmDataToBus(int input_fd
,
406 blink::WebAudioBus
* destination_bus
,
407 size_t number_of_frames
,
408 unsigned number_of_channels
,
409 double file_sample_rate
) {
410 destination_bus
->initialize(number_of_channels
,
414 int16_t pipe_data
[PIPE_BUF
/ sizeof(int16_t)];
415 size_t decoded_frames
= 0;
416 size_t current_sample_in_frame
= 0;
419 while ((nread
= HANDLE_EINTR(read(input_fd
, pipe_data
, sizeof(pipe_data
)))) >
421 size_t samples_in_pipe
= nread
/ sizeof(int16_t);
423 // The pipe may not contain a whole number of frames. This is
424 // especially true if the number of channels is greater than
425 // 2. Thus, keep track of which sample in a frame is being
426 // processed, so we handle the boundary at the end of the pipe
428 for (size_t m
= 0; m
< samples_in_pipe
; ++m
) {
429 if (decoded_frames
>= number_of_frames
)
432 destination_bus
->channelData(current_sample_in_frame
)[decoded_frames
] =
433 ConvertSampleToFloat(pipe_data
[m
]);
434 ++current_sample_in_frame
;
436 if (current_sample_in_frame
>= number_of_channels
) {
437 current_sample_in_frame
= 0;
443 // number_of_frames is only an estimate. Resize the buffer with the
444 // actual number of received frames.
445 if (decoded_frames
< number_of_frames
)
446 destination_bus
->resizeSmaller(decoded_frames
);
449 // The number of frames is unknown, so keep reading and buffering
450 // until there's no more data and then copy the data to the
452 static void BufferAndCopyPcmDataToBus(int input_fd
,
453 blink::WebAudioBus
* destination_bus
,
454 unsigned number_of_channels
,
455 double file_sample_rate
) {
456 int16_t pipe_data
[PIPE_BUF
/ sizeof(int16_t)];
457 std::vector
<int16_t> decoded_samples
;
460 while ((nread
= HANDLE_EINTR(read(input_fd
, pipe_data
, sizeof(pipe_data
)))) >
462 size_t samples_in_pipe
= nread
/ sizeof(int16_t);
463 if (decoded_samples
.size() + samples_in_pipe
> decoded_samples
.capacity()) {
464 decoded_samples
.reserve(std::max(samples_in_pipe
,
465 2 * decoded_samples
.capacity()));
468 pipe_data
+ samples_in_pipe
,
469 back_inserter(decoded_samples
));
472 DVLOG(1) << "Total samples read = " << decoded_samples
.size();
474 // Convert the samples and save them in the audio bus.
475 size_t number_of_samples
= decoded_samples
.size();
476 size_t number_of_frames
= decoded_samples
.size() / number_of_channels
;
477 size_t decoded_frames
= 0;
479 destination_bus
->initialize(number_of_channels
,
483 for (size_t m
= 0; m
< number_of_samples
; m
+= number_of_channels
) {
484 for (size_t k
= 0; k
< number_of_channels
; ++k
) {
485 int16_t sample
= decoded_samples
[m
+ k
];
486 destination_bus
->channelData(k
)[decoded_frames
] =
487 ConvertSampleToFloat(sample
);
492 // number_of_frames is only an estimate. Resize the buffer with the
493 // actual number of received frames.
494 if (decoded_frames
< number_of_frames
)
495 destination_bus
->resizeSmaller(decoded_frames
);
498 static bool TryWAVEFileDecoder(blink::WebAudioBus
* destination_bus
,
499 const uint8_t* encoded_data
,
501 WAVEDecoder
decoder(encoded_data
, data_size
);
503 return decoder
.DecodeWAVEFile(destination_bus
);
506 // To decode audio data, we want to use the Android MediaCodec class.
507 // But this can't run in a sandboxed process so we need initiate the
508 // request to MediaCodec in the browser. To do this, we create a
509 // shared memory buffer that holds the audio data. We send a message
510 // to the browser to start the decoder using this buffer and one end
511 // of a pipe. The MediaCodec class will decode the data from the
512 // shared memory and write the PCM samples back to us over a pipe.
513 bool DecodeAudioFileData(blink::WebAudioBus
* destination_bus
, const char* data
,
515 scoped_refptr
<ThreadSafeSender
> sender
) {
516 // Try to decode the data as a WAVE file first. If it can't be
517 // decoded, use MediaCodec. See crbug.com/259048.
518 if (TryWAVEFileDecoder(
519 destination_bus
, reinterpret_cast<const uint8_t*>(data
), data_size
)) {
523 AudioDecoderIO
audio_decoder(data
, data_size
);
525 if (!audio_decoder
.IsValid())
528 base::SharedMemoryHandle encoded_data_handle
;
529 audio_decoder
.ShareEncodedToProcess(&encoded_data_handle
);
530 base::FileDescriptor
fd(audio_decoder
.write_fd(), true);
532 DVLOG(1) << "DecodeAudioFileData: Starting MediaCodec";
534 // Start MediaCodec processing in the browser which will read from
535 // encoded_data_handle for our shared memory and write the decoded
536 // PCM samples (16-bit integer) to our pipe.
538 sender
->Send(new ViewHostMsg_RunWebAudioMediaCodec(
539 encoded_data_handle
, fd
, data_size
));
541 // First, read the number of channels, the sample rate, and the
542 // number of frames and a flag indicating if the file is an
543 // ogg/vorbis file. This must be coordinated with
544 // WebAudioMediaCodecBridge!
546 // If we know the number of samples, we can create the destination
547 // bus directly and do the conversion directly to the bus instead of
548 // buffering up everything before saving the data to the bus.
550 int input_fd
= audio_decoder
.read_fd();
551 struct media::WebAudioMediaCodecInfo info
;
553 DVLOG(1) << "Reading audio file info from fd " << input_fd
;
554 ssize_t nread
= HANDLE_EINTR(read(input_fd
, &info
, sizeof(info
)));
555 DVLOG(1) << "read: " << nread
<< " bytes:\n"
556 << " 0: number of channels = " << info
.channel_count
<< "\n"
557 << " 1: sample rate = " << info
.sample_rate
<< "\n"
558 << " 2: number of frames = " << info
.number_of_frames
<< "\n";
560 if (nread
!= sizeof(info
))
563 unsigned number_of_channels
= info
.channel_count
;
564 double file_sample_rate
= static_cast<double>(info
.sample_rate
);
565 size_t number_of_frames
= info
.number_of_frames
;
568 if (!number_of_channels
||
569 number_of_channels
> media::limits::kMaxChannels
||
570 file_sample_rate
< media::limits::kMinSampleRate
||
571 file_sample_rate
> media::limits::kMaxSampleRate
) {
575 if (number_of_frames
> 0) {
576 CopyPcmDataToBus(input_fd
,
582 BufferAndCopyPcmDataToBus(input_fd
,
591 } // namespace content