 Chromium Code Reviews
 Chromium Code Reviews Issue 2466463005:
  Support (E)AC3 passthrough
    
  
    Issue 2466463005:
  Support (E)AC3 passthrough 
  | OLD | NEW | 
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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. | |
| 4 | |
| 5 #include "media/audio/android/audio_track_output_stream.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "base/single_thread_task_runner.h" | |
| 11 #include "base/time/default_tick_clock.h" | |
| 12 #include "jni/AudioTrackOutputStream_jni.h" | |
| 13 #include "media/audio/audio_manager_base.h" | |
| 14 | |
| 15 using base::android::AttachCurrentThread; | |
| 16 | |
| 17 namespace media { | |
| 18 | |
| 19 // Android audio format. For more information, please see: | |
| 20 // https://developer.android.com/reference/android/media/AudioFormat.html | |
| 21 enum { | |
| 22 kEncodingPcmFloat = 4, // ENCODING_PCM_FLOAT | |
| 23 kEncodingAc3 = 5, // ENCODING_AC3 | |
| 24 kEncodingEac3 = 6, // ENCODING_E_AC3 | |
| 25 }; | |
| 26 | |
| 27 AudioTrackOutputStream::AudioTrackOutputStream(AudioManagerBase* manager, | |
| 28 const AudioParameters& params) | |
| 29 : params_(params), | |
| 30 audio_manager_(manager), | |
| 31 callback_(nullptr), | |
| 
DaleCurtis
2017/06/15 21:46:31
Inline initialize these parameters in the header f
 
AndyWu
2017/08/02 01:43:38
Done.
 | |
| 32 audio_bus_(AudioBus::Create(params_)), | |
| 33 muted_(false), | |
| 34 volume_(1.0), | |
| 35 total_read_frames_(0), | |
| 36 tick_clock_(new base::DefaultTickClock()) { | |
| 
DaleCurtis
2017/06/15 21:46:31
No need for this unless you're going to add a test
 
AndyWu
2017/08/02 01:43:38
Done.
 | |
| 37 audio_bus_->Zero(); | |
| 38 } | |
| 39 | |
| 40 AudioTrackOutputStream::~AudioTrackOutputStream() { | |
| 41 DCHECK(!callback_); | |
| 42 } | |
| 43 | |
| 44 bool AudioTrackOutputStream::Open() { | |
| 45 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); | |
| 46 JNIEnv* env = AttachCurrentThread(); | |
| 47 j_audio_output_stream_.Reset(Java_AudioTrackOutputStream_create(env)); | |
| 48 | |
| 49 int format = kEncodingPcmFloat; | |
| 50 if (params_.IsBitstreamFormat()) { | |
| 51 if (params_.format() == AudioParameters::AUDIO_BITSTREAM_AC3) { | |
| 52 format = kEncodingAc3; | |
| 53 } else if (params_.format() == AudioParameters::AUDIO_BITSTREAM_EAC3) { | |
| 54 format = kEncodingEac3; | |
| 55 } else { | |
| 56 NOTREACHED(); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 return Java_AudioTrackOutputStream_open(env, j_audio_output_stream_.obj(), | |
| 61 params_.channels(), | |
| 62 params_.sample_rate(), format); | |
| 63 } | |
| 64 | |
| 65 void AudioTrackOutputStream::Start(AudioSourceCallback* callback) { | |
| 66 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); | |
| 67 callback_ = callback; | |
| 68 total_read_frames_ = 0; | |
| 69 Java_AudioTrackOutputStream_start(AttachCurrentThread(), | |
| 70 j_audio_output_stream_.obj(), | |
| 71 reinterpret_cast<intptr_t>(this)); | |
| 72 } | |
| 73 | |
| 74 void AudioTrackOutputStream::Stop() { | |
| 75 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); | |
| 76 Java_AudioTrackOutputStream_stop(AttachCurrentThread(), | |
| 77 j_audio_output_stream_.obj()); | |
| 78 callback_ = nullptr; | |
| 79 } | |
| 80 | |
| 81 void AudioTrackOutputStream::Close() { | |
| 82 DCHECK(!callback_); | |
| 83 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); | |
| 84 | |
| 85 Java_AudioTrackOutputStream_close(AttachCurrentThread(), | |
| 86 j_audio_output_stream_.obj()); | |
| 87 audio_manager_->ReleaseOutputStream(this); | |
| 88 } | |
| 89 | |
| 90 void AudioTrackOutputStream::SetMute(bool muted) { | |
| 91 if (muted_ == muted) | |
| 92 return; | |
| 93 | |
| 94 muted_ = muted; | |
| 95 Java_AudioTrackOutputStream_setVolume(AttachCurrentThread(), | |
| 96 j_audio_output_stream_.obj(), | |
| 97 muted_ ? 0.0 : volume_); | |
| 98 } | |
| 99 | |
| 100 void AudioTrackOutputStream::SetVolume(double volume) { | |
| 101 // Track |volume_| since AudioTrack uses a scaled value. | |
| 102 volume_ = volume; | |
| 103 if (muted_) | |
| 104 return; | |
| 105 | |
| 106 Java_AudioTrackOutputStream_setVolume(AttachCurrentThread(), | |
| 107 j_audio_output_stream_.obj(), volume); | |
| 108 }; | |
| 109 | |
| 110 void AudioTrackOutputStream::GetVolume(double* volume) { | |
| 111 *volume = volume_; | |
| 112 }; | |
| 113 | |
| 114 // AudioOutputStream::SourceCallback implementation methods called from Java. | |
| 115 int AudioTrackOutputStream::OnMoreData(JNIEnv* env, | |
| 116 jobject obj, | |
| 117 jobject audio_data, | |
| 118 int total_played_frames) { | |
| 
DaleCurtis
2017/06/15 21:46:31
As Chris notes, this should be an int64_t.
 
AndyWu
2017/08/02 01:43:38
AudioTrack.getPlaybackHeadPosition()[1] returns a
 
DaleCurtis
2017/08/03 01:38:10
Overflow isn't defined for signed types, so if you
 
AndyWu
2017/08/03 17:11:17
Well, I consider 0x7FFFFFFF + 1 = 0x80000000 is ov
 
DaleCurtis
2017/08/03 17:22:55
Thanks for changing it. For future reference, what
 
AndyWu
2017/08/03 21:58:45
Thanks for the great information. :) It does make
 | |
| 119 if (!callback_) | |
| 120 return 0; | |
| 121 | |
| 122 int delay_in_frame = total_read_frames_ - total_played_frames; | |
| 
DaleCurtis
2017/06/15 21:46:31
Ditto; int64_t.
 
AndyWu
2017/08/02 01:43:38
Done.
 | |
| 123 if (delay_in_frame < 0) | |
| 
DaleCurtis
2017/06/15 21:46:31
Should be impossible?, DCHECK instead?
 
AndyWu
2017/08/02 01:43:38
Normally, it should not happen. However, it could
 | |
| 124 delay_in_frame = 0; | |
| 125 base::TimeDelta delay = base::TimeDelta::FromSecondsD( | |
| 
DaleCurtis
2017/06/15 21:46:31
Use AudioTimestampHelper::FramesToTime().
 
AndyWu
2017/08/02 01:43:38
Done.
 | |
| 126 static_cast<double>(delay_in_frame) / params_.sample_rate()); | |
| 127 | |
| 128 callback_->OnMoreData(delay, tick_clock_->NowTicks(), 0, audio_bus_.get()); | |
| 129 | |
| 130 if (audio_bus_->data_size() <= 0) | |
| 131 return 0; | |
| 132 | |
| 133 total_read_frames_ += audio_bus_->frames(); | |
| 134 | |
| 135 void* native_bus = env->GetDirectBufferAddress(audio_data); | |
| 
DaleCurtis
2017/06/15 21:46:31
Get this pointer ahead of time and use AudioBus::W
 
AndyWu
2017/08/02 01:43:38
TBD
 | |
| 136 memcpy(native_bus, audio_bus_->channel(0), audio_bus_->data_size()); | |
| 137 return audio_bus_->data_size(); | |
| 138 } | |
| 139 | |
| 140 void AudioTrackOutputStream::OnError(JNIEnv* env, jobject obj) { | |
| 141 DCHECK(callback_); | |
| 142 callback_->OnError(); | |
| 143 } | |
| 144 | |
| 145 // static | |
| 146 bool AudioTrackOutputStream::RegisterAudioTrackOutputStream(JNIEnv* env) { | |
| 147 return RegisterNativesImpl(env); | |
| 148 } | |
| 149 | |
| 150 } // namespace media | |
| OLD | NEW |