OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/android/audio_decoder_android.h" | 5 #include "content/renderer/media/android/audio_decoder_android.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <limits.h> | 9 #include <limits.h> |
10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 // basic guide to the WAVE file format. | 106 // basic guide to the WAVE file format. |
107 class WAVEDecoder { | 107 class WAVEDecoder { |
108 public: | 108 public: |
109 WAVEDecoder(const uint8* data, size_t data_size); | 109 WAVEDecoder(const uint8* data, size_t data_size); |
110 ~WAVEDecoder(); | 110 ~WAVEDecoder(); |
111 | 111 |
112 // Try to decode the data as a WAVE file. If the data is a supported | 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 | 113 // WAVE file, |destination_bus| is filled with the decoded data and |
114 // DecodeWAVEFile returns true. Otherwise, DecodeWAVEFile returns | 114 // DecodeWAVEFile returns true. Otherwise, DecodeWAVEFile returns |
115 // false. | 115 // false. |
116 bool DecodeWAVEFile(WebKit::WebAudioBus* destination_bus); | 116 bool DecodeWAVEFile(blink::WebAudioBus* destination_bus); |
117 | 117 |
118 private: | 118 private: |
119 // Minimum number of bytes in a WAVE file to hold all of the data we | 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. | 120 // need to interpret it as a WAVE file. |
121 static const unsigned kMinimumWAVLength = 44; | 121 static const unsigned kMinimumWAVLength = 44; |
122 | 122 |
123 // Number of bytes in the chunk ID field. | 123 // Number of bytes in the chunk ID field. |
124 static const unsigned kChunkIDLength = 4; | 124 static const unsigned kChunkIDLength = 4; |
125 | 125 |
126 // Number of bytes in the chunk size field. | 126 // Number of bytes in the chunk size field. |
(...skipping 23 matching lines...) Expand all Loading... |
150 // Read a WAVE chunk header including the chunk ID and chunk size. | 150 // Read a WAVE chunk header including the chunk ID and chunk size. |
151 // Returns false if the header could not be read. | 151 // Returns false if the header could not be read. |
152 bool ReadChunkHeader(); | 152 bool ReadChunkHeader(); |
153 | 153 |
154 // Read and parse the "fmt" chunk. Returns false if the fmt chunk | 154 // Read and parse the "fmt" chunk. Returns false if the fmt chunk |
155 // could not be read or contained unsupported formats. | 155 // could not be read or contained unsupported formats. |
156 bool ReadFMTChunk(); | 156 bool ReadFMTChunk(); |
157 | 157 |
158 // Read data chunk and save it to |destination_bus|. Returns false | 158 // Read data chunk and save it to |destination_bus|. Returns false |
159 // if the data chunk could not be read correctly. | 159 // if the data chunk could not be read correctly. |
160 bool CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus); | 160 bool CopyDataChunkToBus(blink::WebAudioBus* destination_bus); |
161 | 161 |
162 // The WAVE chunk ID that identifies the chunk. | 162 // The WAVE chunk ID that identifies the chunk. |
163 uint8_t chunk_id_[kChunkIDLength]; | 163 uint8_t chunk_id_[kChunkIDLength]; |
164 | 164 |
165 // The number of bytes in the data portion of the chunk. | 165 // The number of bytes in the data portion of the chunk. |
166 size_t chunk_size_; | 166 size_t chunk_size_; |
167 | 167 |
168 // The current position within the WAVE file. | 168 // The current position within the WAVE file. |
169 const uint8_t* buffer_; | 169 const uint8_t* buffer_; |
170 | 170 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 // We only support 8, 16, and 24 bits per sample. | 286 // We only support 8, 16, and 24 bits per sample. |
287 if (bits_per_sample == 8 || bits_per_sample == 16 || bits_per_sample == 24) { | 287 if (bits_per_sample == 8 || bits_per_sample == 16 || bits_per_sample == 24) { |
288 bytes_per_sample_ = bits_per_sample / 8; | 288 bytes_per_sample_ = bits_per_sample / 8; |
289 return true; | 289 return true; |
290 } | 290 } |
291 | 291 |
292 DVLOG(1) << "Unsupported bits per sample: " << bits_per_sample; | 292 DVLOG(1) << "Unsupported bits per sample: " << bits_per_sample; |
293 return false; | 293 return false; |
294 } | 294 } |
295 | 295 |
296 bool WAVEDecoder::CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus) { | 296 bool WAVEDecoder::CopyDataChunkToBus(blink::WebAudioBus* destination_bus) { |
297 // The data chunk contains the audio data itself. | 297 // The data chunk contains the audio data itself. |
298 if (!bytes_per_sample_ || bytes_per_sample_ > kMaximumBytesPerSample) { | 298 if (!bytes_per_sample_ || bytes_per_sample_ > kMaximumBytesPerSample) { |
299 DVLOG(1) << "WARNING: data chunk without preceeding fmt chunk," | 299 DVLOG(1) << "WARNING: data chunk without preceeding fmt chunk," |
300 << " or invalid bytes per sample."; | 300 << " or invalid bytes per sample."; |
301 return false; | 301 return false; |
302 } | 302 } |
303 | 303 |
304 VLOG(0) << "Decoding WAVE file: " << number_of_channels_ << " channels, " | 304 VLOG(0) << "Decoding WAVE file: " << number_of_channels_ << " channels, " |
305 << sample_rate_ << " kHz, " | 305 << sample_rate_ << " kHz, " |
306 << chunk_size_ / bytes_per_sample_ / number_of_channels_ | 306 << chunk_size_ / bytes_per_sample_ / number_of_channels_ |
(...skipping 12 matching lines...) Expand all Loading... |
319 int16_t sample = ReadPCMSample(buffer_); | 319 int16_t sample = ReadPCMSample(buffer_); |
320 | 320 |
321 buffer_ += bytes_per_sample_; | 321 buffer_ += bytes_per_sample_; |
322 destination_bus->channelData(k)[m] = ConvertSampleToFloat(sample); | 322 destination_bus->channelData(k)[m] = ConvertSampleToFloat(sample); |
323 } | 323 } |
324 } | 324 } |
325 | 325 |
326 return true; | 326 return true; |
327 } | 327 } |
328 | 328 |
329 bool WAVEDecoder::DecodeWAVEFile(WebKit::WebAudioBus* destination_bus) { | 329 bool WAVEDecoder::DecodeWAVEFile(blink::WebAudioBus* destination_bus) { |
330 // Parse and decode WAVE file. If we can't parse it, return false. | 330 // Parse and decode WAVE file. If we can't parse it, return false. |
331 | 331 |
332 if (buffer_ + kMinimumWAVLength > buffer_end_) { | 332 if (buffer_ + kMinimumWAVLength > buffer_end_) { |
333 DVLOG(1) << "Buffer too small to contain full WAVE header: "; | 333 DVLOG(1) << "Buffer too small to contain full WAVE header: "; |
334 return false; | 334 return false; |
335 } | 335 } |
336 | 336 |
337 // Do we have a RIFF file? | 337 // Do we have a RIFF file? |
338 ReadChunkHeader(); | 338 ReadChunkHeader(); |
339 if (memcmp(chunk_id_, "RIFF", kChunkIDLength) != 0) { | 339 if (memcmp(chunk_id_, "RIFF", kChunkIDLength) != 0) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 // If we get here, that means we didn't find a data chunk, so we | 388 // If we get here, that means we didn't find a data chunk, so we |
389 // couldn't handle this WAVE file. | 389 // couldn't handle this WAVE file. |
390 | 390 |
391 return false; | 391 return false; |
392 } | 392 } |
393 | 393 |
394 // The number of frames is known so preallocate the destination | 394 // The number of frames is known so preallocate the destination |
395 // bus and copy the pcm data to the destination bus as it's being | 395 // bus and copy the pcm data to the destination bus as it's being |
396 // received. | 396 // received. |
397 static void CopyPcmDataToBus(int input_fd, | 397 static void CopyPcmDataToBus(int input_fd, |
398 WebKit::WebAudioBus* destination_bus, | 398 blink::WebAudioBus* destination_bus, |
399 size_t number_of_frames, | 399 size_t number_of_frames, |
400 unsigned number_of_channels, | 400 unsigned number_of_channels, |
401 double file_sample_rate) { | 401 double file_sample_rate) { |
402 destination_bus->initialize(number_of_channels, | 402 destination_bus->initialize(number_of_channels, |
403 number_of_frames, | 403 number_of_frames, |
404 file_sample_rate); | 404 file_sample_rate); |
405 | 405 |
406 int16_t pipe_data[PIPE_BUF / sizeof(int16_t)]; | 406 int16_t pipe_data[PIPE_BUF / sizeof(int16_t)]; |
407 size_t decoded_frames = 0; | 407 size_t decoded_frames = 0; |
408 ssize_t nread; | 408 ssize_t nread; |
(...skipping 17 matching lines...) Expand all Loading... |
426 // number_of_frames is only an estimate. Resize the buffer with the | 426 // number_of_frames is only an estimate. Resize the buffer with the |
427 // actual number of received frames. | 427 // actual number of received frames. |
428 if (decoded_frames < number_of_frames) | 428 if (decoded_frames < number_of_frames) |
429 destination_bus->resizeSmaller(decoded_frames); | 429 destination_bus->resizeSmaller(decoded_frames); |
430 } | 430 } |
431 | 431 |
432 // The number of frames is unknown, so keep reading and buffering | 432 // The number of frames is unknown, so keep reading and buffering |
433 // until there's no more data and then copy the data to the | 433 // until there's no more data and then copy the data to the |
434 // destination bus. | 434 // destination bus. |
435 static void BufferAndCopyPcmDataToBus(int input_fd, | 435 static void BufferAndCopyPcmDataToBus(int input_fd, |
436 WebKit::WebAudioBus* destination_bus, | 436 blink::WebAudioBus* destination_bus, |
437 unsigned number_of_channels, | 437 unsigned number_of_channels, |
438 double file_sample_rate) { | 438 double file_sample_rate) { |
439 int16_t pipe_data[PIPE_BUF / sizeof(int16_t)]; | 439 int16_t pipe_data[PIPE_BUF / sizeof(int16_t)]; |
440 std::vector<int16_t> decoded_samples; | 440 std::vector<int16_t> decoded_samples; |
441 ssize_t nread; | 441 ssize_t nread; |
442 | 442 |
443 while ((nread = HANDLE_EINTR(read(input_fd, pipe_data, sizeof(pipe_data)))) > | 443 while ((nread = HANDLE_EINTR(read(input_fd, pipe_data, sizeof(pipe_data)))) > |
444 0) { | 444 0) { |
445 size_t samples_in_pipe = nread / sizeof(int16_t); | 445 size_t samples_in_pipe = nread / sizeof(int16_t); |
446 if (decoded_samples.size() + samples_in_pipe > decoded_samples.capacity()) { | 446 if (decoded_samples.size() + samples_in_pipe > decoded_samples.capacity()) { |
(...skipping 24 matching lines...) Expand all Loading... |
471 } | 471 } |
472 ++decoded_frames; | 472 ++decoded_frames; |
473 } | 473 } |
474 | 474 |
475 // number_of_frames is only an estimate. Resize the buffer with the | 475 // number_of_frames is only an estimate. Resize the buffer with the |
476 // actual number of received frames. | 476 // actual number of received frames. |
477 if (decoded_frames < number_of_frames) | 477 if (decoded_frames < number_of_frames) |
478 destination_bus->resizeSmaller(decoded_frames); | 478 destination_bus->resizeSmaller(decoded_frames); |
479 } | 479 } |
480 | 480 |
481 static bool TryWAVEFileDecoder(WebKit::WebAudioBus* destination_bus, | 481 static bool TryWAVEFileDecoder(blink::WebAudioBus* destination_bus, |
482 const uint8_t* encoded_data, | 482 const uint8_t* encoded_data, |
483 size_t data_size) { | 483 size_t data_size) { |
484 WAVEDecoder decoder(encoded_data, data_size); | 484 WAVEDecoder decoder(encoded_data, data_size); |
485 | 485 |
486 return decoder.DecodeWAVEFile(destination_bus); | 486 return decoder.DecodeWAVEFile(destination_bus); |
487 } | 487 } |
488 | 488 |
489 // To decode audio data, we want to use the Android MediaCodec class. | 489 // To decode audio data, we want to use the Android MediaCodec class. |
490 // But this can't run in a sandboxed process so we need initiate the | 490 // But this can't run in a sandboxed process so we need initiate the |
491 // request to MediaCodec in the browser. To do this, we create a | 491 // request to MediaCodec in the browser. To do this, we create a |
492 // shared memory buffer that holds the audio data. We send a message | 492 // shared memory buffer that holds the audio data. We send a message |
493 // to the browser to start the decoder using this buffer and one end | 493 // to the browser to start the decoder using this buffer and one end |
494 // of a pipe. The MediaCodec class will decode the data from the | 494 // of a pipe. The MediaCodec class will decode the data from the |
495 // shared memory and write the PCM samples back to us over a pipe. | 495 // shared memory and write the PCM samples back to us over a pipe. |
496 bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, const char* data, | 496 bool DecodeAudioFileData(blink::WebAudioBus* destination_bus, const char* data, |
497 size_t data_size, double sample_rate, | 497 size_t data_size, double sample_rate, |
498 scoped_refptr<ThreadSafeSender> sender) { | 498 scoped_refptr<ThreadSafeSender> sender) { |
499 // Try to decode the data as a WAVE file first. If it can't be | 499 // Try to decode the data as a WAVE file first. If it can't be |
500 // decoded, use MediaCodec. See crbug.com/259048. | 500 // decoded, use MediaCodec. See crbug.com/259048. |
501 if (TryWAVEFileDecoder( | 501 if (TryWAVEFileDecoder( |
502 destination_bus, reinterpret_cast<const uint8_t*>(data), data_size)) { | 502 destination_bus, reinterpret_cast<const uint8_t*>(data), data_size)) { |
503 return true; | 503 return true; |
504 } | 504 } |
505 | 505 |
506 AudioDecoderIO audio_decoder(data, data_size); | 506 AudioDecoderIO audio_decoder(data, data_size); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 BufferAndCopyPcmDataToBus(input_fd, | 565 BufferAndCopyPcmDataToBus(input_fd, |
566 destination_bus, | 566 destination_bus, |
567 number_of_channels, | 567 number_of_channels, |
568 file_sample_rate); | 568 file_sample_rate); |
569 } | 569 } |
570 | 570 |
571 return true; | 571 return true; |
572 } | 572 } |
573 | 573 |
574 } // namespace content | 574 } // namespace content |
OLD | NEW |