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 package org.chromium.media; | 5 package org.chromium.media; |
6 | 6 |
7 import android.media.AudioFormat; | 7 import android.media.AudioFormat; |
8 import android.media.AudioManager; | 8 import android.media.AudioManager; |
9 import android.media.AudioTrack; | 9 import android.media.AudioTrack; |
10 import android.media.MediaCodec; | 10 import android.media.MediaCodec; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 Log.e(TAG, "Failed to dequeue input buffer", e); | 278 Log.e(TAG, "Failed to dequeue input buffer", e); |
279 } | 279 } |
280 return new DequeueInputResult(status, index); | 280 return new DequeueInputResult(status, index); |
281 } | 281 } |
282 | 282 |
283 @CalledByNative | 283 @CalledByNative |
284 private int flush() { | 284 private int flush() { |
285 try { | 285 try { |
286 mFlushed = true; | 286 mFlushed = true; |
287 if (mAudioTrack != null) { | 287 if (mAudioTrack != null) { |
| 288 // Need to call pause() here, or otherwise flush() is a no-op. |
| 289 mAudioTrack.pause(); |
288 mAudioTrack.flush(); | 290 mAudioTrack.flush(); |
289 } | 291 } |
290 mMediaCodec.flush(); | 292 mMediaCodec.flush(); |
291 } catch (IllegalStateException e) { | 293 } catch (IllegalStateException e) { |
292 Log.e(TAG, "Failed to flush MediaCodec", e); | 294 Log.e(TAG, "Failed to flush MediaCodec", e); |
293 return MEDIA_CODEC_ERROR; | 295 return MEDIA_CODEC_ERROR; |
294 } | 296 } |
295 return MEDIA_CODEC_OK; | 297 return MEDIA_CODEC_OK; |
296 } | 298 } |
297 | 299 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 return false; | 520 return false; |
519 } | 521 } |
520 } | 522 } |
521 return true; | 523 return true; |
522 } catch (IllegalStateException e) { | 524 } catch (IllegalStateException e) { |
523 Log.e(TAG, "Cannot configure the audio codec", e); | 525 Log.e(TAG, "Cannot configure the audio codec", e); |
524 } | 526 } |
525 return false; | 527 return false; |
526 } | 528 } |
527 | 529 |
| 530 /** |
| 531 * Play the audio buffer that is passed in. |
| 532 * |
| 533 * @param buf Audio buffer to be rendered. |
| 534 * @return The number of frames that have already been consumed by the |
| 535 * hardware. This number resets to 0 after each flush call. |
| 536 */ |
528 @CalledByNative | 537 @CalledByNative |
529 private void playOutputBuffer(byte[] buf) { | 538 private long playOutputBuffer(byte[] buf) { |
530 if (mAudioTrack != null) { | 539 if (mAudioTrack == null) { |
531 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) { | 540 return 0; |
532 mAudioTrack.play(); | |
533 } | |
534 int size = mAudioTrack.write(buf, 0, buf.length); | |
535 if (buf.length != size) { | |
536 Log.i(TAG, "Failed to send all data to audio output, expected si
ze: " + | |
537 buf.length + ", actual size: " + size); | |
538 } | |
539 } | 541 } |
| 542 |
| 543 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) { |
| 544 mAudioTrack.play(); |
| 545 } |
| 546 int size = mAudioTrack.write(buf, 0, buf.length); |
| 547 if (buf.length != size) { |
| 548 Log.i(TAG, "Failed to send all data to audio output, expected size:
" + |
| 549 buf.length + ", actual size: " + size); |
| 550 } |
| 551 // TODO(qinmin): Returning the head position allows us to estimate |
| 552 // the current presentation time in native code. However, it is |
| 553 // better to use AudioTrack.getCurrentTimestamp() to get the last |
| 554 // known time when a frame is played. However, we will need to |
| 555 // convert the java nano time to C++ timestamp. |
| 556 // If the stream runs too long, getPlaybackHeadPosition() could |
| 557 // overflow. AudioTimestampHelper in MediaSourcePlayer has the same |
| 558 // issue. See http://crbug.com/358801. |
| 559 return mAudioTrack.getPlaybackHeadPosition(); |
540 } | 560 } |
541 | 561 |
542 @CalledByNative | 562 @CalledByNative |
543 private void setVolume(double volume) { | 563 private void setVolume(double volume) { |
544 if (mAudioTrack != null) { | 564 if (mAudioTrack != null) { |
545 mAudioTrack.setStereoVolume((float) volume, (float) volume); | 565 mAudioTrack.setStereoVolume((float) volume, (float) volume); |
546 } | 566 } |
547 } | 567 } |
548 | 568 |
549 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) { | 569 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) { |
(...skipping 14 matching lines...) Expand all Loading... |
564 return AudioFormat.CHANNEL_OUT_QUAD; | 584 return AudioFormat.CHANNEL_OUT_QUAD; |
565 case 6: | 585 case 6: |
566 return AudioFormat.CHANNEL_OUT_5POINT1; | 586 return AudioFormat.CHANNEL_OUT_5POINT1; |
567 case 8: | 587 case 8: |
568 return AudioFormat.CHANNEL_OUT_7POINT1; | 588 return AudioFormat.CHANNEL_OUT_7POINT1; |
569 default: | 589 default: |
570 return AudioFormat.CHANNEL_OUT_DEFAULT; | 590 return AudioFormat.CHANNEL_OUT_DEFAULT; |
571 } | 591 } |
572 } | 592 } |
573 } | 593 } |
OLD | NEW |