| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "media/base/filter_host.h" | 5 #include "media/base/filter_host.h" |
| 6 #include "media/filters/audio_renderer_base.h" | 6 #include "media/filters/audio_renderer_base.h" |
| 7 | 7 |
| 8 namespace media { | 8 namespace media { |
| 9 | 9 |
| 10 // The maximum size of the queue, which also acts as the number of initial reads | 10 // The maximum size of the queue, which also acts as the number of initial reads |
| 11 // to perform for buffering. The size of the queue should never exceed this | 11 // to perform for buffering. The size of the queue should never exceed this |
| 12 // number since we read only after we've dequeued and released a buffer in | 12 // number since we read only after we've dequeued and released a buffer in |
| 13 // callback thread. | 13 // callback thread. |
| 14 // | 14 // |
| 15 // This is sort of a magic number, but for 44.1kHz stereo audio this will give | 15 // This is sort of a magic number, but for 44.1kHz stereo audio this will give |
| 16 // us enough data to fill approximately 4 complete callback buffers. | 16 // us enough data to fill approximately 4 complete callback buffers. |
| 17 const size_t AudioRendererBase::kDefaultMaxQueueSize = 16; | 17 const size_t AudioRendererBase::kDefaultMaxQueueSize = 16; |
| 18 | 18 |
| 19 AudioRendererBase::AudioRendererBase(size_t max_queue_size) | 19 AudioRendererBase::AudioRendererBase(size_t max_queue_size) |
| 20 : max_queue_size_(max_queue_size), | 20 : max_queue_size_(max_queue_size), |
| 21 data_offset_(0), | 21 data_offset_(0), |
| 22 initialized_(false), | 22 state_(kUninitialized), |
| 23 stopped_(false) { | 23 pending_reads_(0) { |
| 24 } | 24 } |
| 25 | 25 |
| 26 AudioRendererBase::~AudioRendererBase() { | 26 AudioRendererBase::~AudioRendererBase() { |
| 27 // Stop() should have been called and OnReadComplete() should have stopped | 27 // Stop() should have been called and OnReadComplete() should have stopped |
| 28 // enqueuing data. | 28 // enqueuing data. |
| 29 DCHECK(stopped_); | 29 DCHECK(state_ == kUninitialized || state_ == kStopped); |
| 30 DCHECK(queue_.empty()); | 30 DCHECK(queue_.empty()); |
| 31 } | 31 } |
| 32 | 32 |
| 33 void AudioRendererBase::Play(FilterCallback* callback) { |
| 34 AutoLock auto_lock(lock_); |
| 35 DCHECK_EQ(kPaused, state_); |
| 36 scoped_ptr<FilterCallback> c(callback); |
| 37 state_ = kPlaying; |
| 38 callback->Run(); |
| 39 } |
| 40 |
| 41 void AudioRendererBase::Pause(FilterCallback* callback) { |
| 42 AutoLock auto_lock(lock_); |
| 43 DCHECK_EQ(kPlaying, state_); |
| 44 pause_callback_.reset(callback); |
| 45 state_ = kPaused; |
| 46 |
| 47 // We'll only pause when we've finished all pending reads. |
| 48 if (pending_reads_ == 0) { |
| 49 pause_callback_->Run(); |
| 50 pause_callback_.reset(); |
| 51 } else { |
| 52 state_ = kPaused; |
| 53 } |
| 54 } |
| 55 |
| 33 void AudioRendererBase::Stop() { | 56 void AudioRendererBase::Stop() { |
| 34 OnStop(); | 57 OnStop(); |
| 35 | 58 |
| 36 AutoLock auto_lock(lock_); | 59 AutoLock auto_lock(lock_); |
| 60 state_ = kStopped; |
| 37 queue_.clear(); | 61 queue_.clear(); |
| 38 stopped_ = true; | |
| 39 } | 62 } |
| 40 | 63 |
| 41 void AudioRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { | 64 void AudioRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { |
| 42 AutoLock auto_lock(lock_); | 65 AutoLock auto_lock(lock_); |
| 66 DCHECK_EQ(kPaused, state_); |
| 67 DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed"; |
| 68 state_ = kSeeking; |
| 69 seek_callback_.reset(callback); |
| 70 |
| 71 // Throw away everything and schedule our reads. |
| 43 last_fill_buffer_time_ = base::TimeDelta(); | 72 last_fill_buffer_time_ = base::TimeDelta(); |
| 44 | 73 queue_.clear(); |
| 45 // Clear the queue of decoded packets and release the buffers. Fire as many | 74 data_offset_ = 0; |
| 46 // reads as buffers released. It is safe to schedule reads here because | 75 for (size_t i = 0; i < max_queue_size_; ++i) { |
| 47 // demuxer and decoders should have received the seek signal. | 76 ScheduleRead_Locked(); |
| 48 // TODO(hclam): we should preform prerolling again after each seek to avoid | |
| 49 // glitch or clicking of audio. | |
| 50 while (!queue_.empty()) { | |
| 51 queue_.pop_front(); | |
| 52 ScheduleRead(); | |
| 53 } | 77 } |
| 54 } | 78 } |
| 55 | 79 |
| 56 void AudioRendererBase::Initialize(AudioDecoder* decoder, | 80 void AudioRendererBase::Initialize(AudioDecoder* decoder, |
| 57 FilterCallback* callback) { | 81 FilterCallback* callback) { |
| 58 DCHECK(decoder); | 82 DCHECK(decoder); |
| 59 DCHECK(callback); | 83 DCHECK(callback); |
| 84 DCHECK_EQ(kUninitialized, state_); |
| 85 scoped_ptr<FilterCallback> c(callback); |
| 60 decoder_ = decoder; | 86 decoder_ = decoder; |
| 61 initialize_callback_.reset(callback); | |
| 62 | 87 |
| 63 // Defer initialization until all scheduled reads have completed. | 88 // Defer initialization until all scheduled reads have completed. |
| 64 if (!OnInitialize(decoder_->media_format())) { | 89 if (!OnInitialize(decoder_->media_format())) { |
| 65 host()->SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | 90 host()->SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 66 initialize_callback_->Run(); | 91 callback->Run(); |
| 67 initialize_callback_.reset(); | 92 return; |
| 68 } | 93 } |
| 69 | 94 |
| 70 // Schedule our initial reads. | 95 // Finally, execute the start callback. |
| 71 for (size_t i = 0; i < max_queue_size_; ++i) { | 96 state_ = kPaused; |
| 72 ScheduleRead(); | 97 callback->Run(); |
| 98 } |
| 99 |
| 100 void AudioRendererBase::OnReadComplete(Buffer* buffer_in) { |
| 101 AutoLock auto_lock(lock_); |
| 102 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying); |
| 103 DCHECK_GT(pending_reads_, 0u); |
| 104 --pending_reads_; |
| 105 |
| 106 // If we have stopped don't enqueue, same for end of stream buffer since |
| 107 // it has no data. |
| 108 if (!buffer_in->IsEndOfStream()) { |
| 109 queue_.push_back(buffer_in); |
| 110 DCHECK(queue_.size() <= max_queue_size_); |
| 111 } |
| 112 |
| 113 // Check for our preroll complete condition. |
| 114 if (state_ == kSeeking) { |
| 115 DCHECK(seek_callback_.get()); |
| 116 if (queue_.size() == max_queue_size_ || buffer_in->IsEndOfStream()) { |
| 117 // Transition into paused whether we have data in |queue_| or not. |
| 118 // FillBuffer() will play silence if there's nothing to fill. |
| 119 state_ = kPaused; |
| 120 seek_callback_->Run(); |
| 121 seek_callback_.reset(); |
| 122 } |
| 123 } else if (state_ == kPaused && pending_reads_ == 0) { |
| 124 // No more pending reads! We're now officially "paused". |
| 125 if (pause_callback_.get()) { |
| 126 pause_callback_->Run(); |
| 127 pause_callback_.reset(); |
| 128 } |
| 73 } | 129 } |
| 74 } | 130 } |
| 75 | 131 |
| 76 void AudioRendererBase::OnReadComplete(Buffer* buffer_in) { | |
| 77 bool initialization_complete = false; | |
| 78 { | |
| 79 AutoLock auto_lock(lock_); | |
| 80 // If we have stopped don't enqueue, same for end of stream buffer since | |
| 81 // it has no data. | |
| 82 if (!stopped_ && !buffer_in->IsEndOfStream()) { | |
| 83 queue_.push_back(buffer_in); | |
| 84 DCHECK(queue_.size() <= max_queue_size_); | |
| 85 } | |
| 86 | |
| 87 if (!initialized_) { | |
| 88 // We have completed the initialization when we preroll enough and hit | |
| 89 // the target queue size or the stream has ended. | |
| 90 if (queue_.size() == max_queue_size_ || buffer_in->IsEndOfStream()) | |
| 91 initialization_complete = true; | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 if (initialization_complete) { | |
| 96 if (queue_.empty()) { | |
| 97 // If we say we have initialized but buffer queue is empty, raise an | |
| 98 // error. | |
| 99 host()->SetError(PIPELINE_ERROR_NO_DATA); | |
| 100 } else { | |
| 101 initialized_ = true; | |
| 102 } | |
| 103 initialize_callback_->Run(); | |
| 104 initialize_callback_.reset(); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 // TODO(scherkus): clean up FillBuffer().. it's overly complex!! | 132 // TODO(scherkus): clean up FillBuffer().. it's overly complex!! |
| 109 size_t AudioRendererBase::FillBuffer(uint8* dest, | 133 size_t AudioRendererBase::FillBuffer(uint8* dest, |
| 110 size_t dest_len, | 134 size_t dest_len, |
| 111 float rate, | 135 float rate, |
| 112 const base::TimeDelta& playback_delay) { | 136 const base::TimeDelta& playback_delay) { |
| 113 size_t buffers_released = 0; | |
| 114 size_t dest_written = 0; | 137 size_t dest_written = 0; |
| 115 | 138 |
| 116 // The timestamp of the last buffer written during the last call to | 139 // The timestamp of the last buffer written during the last call to |
| 117 // FillBuffer(). | 140 // FillBuffer(). |
| 118 base::TimeDelta last_fill_buffer_time; | 141 base::TimeDelta last_fill_buffer_time; |
| 119 { | 142 { |
| 120 AutoLock auto_lock(lock_); | 143 AutoLock auto_lock(lock_); |
| 121 | 144 |
| 145 // Mute audio by returning 0 when not playing. |
| 146 if (state_ != kPlaying) { |
| 147 return 0; |
| 148 } |
| 149 |
| 122 // Save a local copy of last fill buffer time and reset the member. | 150 // Save a local copy of last fill buffer time and reset the member. |
| 123 last_fill_buffer_time = last_fill_buffer_time_; | 151 last_fill_buffer_time = last_fill_buffer_time_; |
| 124 last_fill_buffer_time_ = base::TimeDelta(); | 152 last_fill_buffer_time_ = base::TimeDelta(); |
| 125 | 153 |
| 126 // Loop until the buffer has been filled. | 154 // Loop until the buffer has been filled. |
| 127 while (dest_len > 0 && !queue_.empty()) { | 155 while (dest_len > 0 && !queue_.empty()) { |
| 128 scoped_refptr<Buffer> buffer = queue_.front(); | 156 scoped_refptr<Buffer> buffer = queue_.front(); |
| 129 | 157 |
| 130 // Determine how much to copy. | 158 // Determine how much to copy. |
| 159 DCHECK_LE(data_offset_, buffer->GetDataSize()); |
| 131 const uint8* data = buffer->GetData() + data_offset_; | 160 const uint8* data = buffer->GetData() + data_offset_; |
| 132 size_t data_len = buffer->GetDataSize() - data_offset_; | 161 size_t data_len = buffer->GetDataSize() - data_offset_; |
| 133 | 162 |
| 134 // New scaled packet size aligned to 16 to ensure it's on a | 163 // New scaled packet size aligned to 16 to ensure it's on a |
| 135 // channel/sample boundary. Only guaranteed to work for power of 2 | 164 // channel/sample boundary. Only guaranteed to work for power of 2 |
| 136 // number of channels and sample size. | 165 // number of channels and sample size. |
| 137 size_t scaled_data_len = (rate <= 0.0f) ? 0 : | 166 size_t scaled_data_len = (rate <= 0.0f) ? 0 : |
| 138 static_cast<size_t>(data_len / rate) & ~15; | 167 static_cast<size_t>(data_len / rate) & ~15; |
| 139 if (scaled_data_len > dest_len) { | 168 if (scaled_data_len > dest_len) { |
| 140 data_len = (data_len * dest_len / scaled_data_len) & ~15; | 169 data_len = (data_len * dest_len / scaled_data_len) & ~15; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 // Check to see if we're finished with the front buffer. | 204 // Check to see if we're finished with the front buffer. |
| 176 if (buffer->GetDataSize() - data_offset_ < 16) { | 205 if (buffer->GetDataSize() - data_offset_ < 16) { |
| 177 // Update the time. If this is the last buffer in the queue, we'll | 206 // Update the time. If this is the last buffer in the queue, we'll |
| 178 // drop out of the loop before len == 0, so we need to always update | 207 // drop out of the loop before len == 0, so we need to always update |
| 179 // the time here. | 208 // the time here. |
| 180 if (buffer->GetTimestamp().InMicroseconds() > 0) { | 209 if (buffer->GetTimestamp().InMicroseconds() > 0) { |
| 181 last_fill_buffer_time_ = buffer->GetTimestamp() + | 210 last_fill_buffer_time_ = buffer->GetTimestamp() + |
| 182 buffer->GetDuration(); | 211 buffer->GetDuration(); |
| 183 } | 212 } |
| 184 | 213 |
| 185 // Dequeue the buffer. | 214 // Dequeue the buffer and request another. |
| 186 queue_.pop_front(); | 215 queue_.pop_front(); |
| 187 ++buffers_released; | 216 ScheduleRead_Locked(); |
| 188 | 217 |
| 189 // Reset our offset into the front buffer. | 218 // Reset our offset into the front buffer. |
| 190 data_offset_ = 0; | 219 data_offset_ = 0; |
| 191 } else { | 220 } else { |
| 192 // If we're done with the read, compute the time. | 221 // If we're done with the read, compute the time. |
| 193 // Integer divide so multiply before divide to work properly. | 222 // Integer divide so multiply before divide to work properly. |
| 194 int64 us_written = (buffer->GetDuration().InMicroseconds() * | 223 int64 us_written = (buffer->GetDuration().InMicroseconds() * |
| 195 data_offset_) / buffer->GetDataSize(); | 224 data_offset_) / buffer->GetDataSize(); |
| 196 | 225 |
| 197 if (buffer->GetTimestamp().InMicroseconds() > 0) { | 226 if (buffer->GetTimestamp().InMicroseconds() > 0) { |
| 198 last_fill_buffer_time_ = | 227 last_fill_buffer_time_ = |
| 199 buffer->GetTimestamp() + | 228 buffer->GetTimestamp() + |
| 200 base::TimeDelta::FromMicroseconds(us_written); | 229 base::TimeDelta::FromMicroseconds(us_written); |
| 201 } | 230 } |
| 202 } | 231 } |
| 203 } | 232 } |
| 204 | |
| 205 // If we've released any buffers, read more buffers from the decoder. | |
| 206 for (size_t i = 0; i < buffers_released; ++i) { | |
| 207 ScheduleRead(); | |
| 208 } | |
| 209 } | 233 } |
| 210 | 234 |
| 211 // Update the pipeline's time if it was set last time. | 235 // Update the pipeline's time if it was set last time. |
| 212 if (last_fill_buffer_time.InMicroseconds() > 0) { | 236 if (last_fill_buffer_time.InMicroseconds() > 0) { |
| 213 // Adjust the |last_fill_buffer_time| with the playback delay. | 237 // Adjust the |last_fill_buffer_time| with the playback delay. |
| 214 // TODO(hclam): If there is a playback delay, the pipeline would not be | 238 // TODO(hclam): If there is a playback delay, the pipeline would not be |
| 215 // updated with a correct timestamp when the stream is played at the very | 239 // updated with a correct timestamp when the stream is played at the very |
| 216 // end since we use decoded packets to trigger time updates. A better | 240 // end since we use decoded packets to trigger time updates. A better |
| 217 // solution is to start a timer when an audio packet is decoded to allow | 241 // solution is to start a timer when an audio packet is decoded to allow |
| 218 // finer time update events. | 242 // finer time update events. |
| 219 if (playback_delay < last_fill_buffer_time) | 243 if (playback_delay < last_fill_buffer_time) |
| 220 last_fill_buffer_time -= playback_delay; | 244 last_fill_buffer_time -= playback_delay; |
| 221 host()->SetTime(last_fill_buffer_time); | 245 host()->SetTime(last_fill_buffer_time); |
| 222 } | 246 } |
| 223 | 247 |
| 224 return dest_written; | 248 return dest_written; |
| 225 } | 249 } |
| 226 | 250 |
| 227 void AudioRendererBase::ScheduleRead() { | 251 void AudioRendererBase::ScheduleRead_Locked() { |
| 252 lock_.AssertAcquired(); |
| 253 DCHECK_LT(pending_reads_, max_queue_size_); |
| 254 ++pending_reads_; |
| 228 decoder_->Read(NewCallback(this, &AudioRendererBase::OnReadComplete)); | 255 decoder_->Read(NewCallback(this, &AudioRendererBase::OnReadComplete)); |
| 229 } | 256 } |
| 230 | 257 |
| 231 // static | 258 // static |
| 232 bool AudioRendererBase::ParseMediaFormat(const MediaFormat& media_format, | 259 bool AudioRendererBase::ParseMediaFormat(const MediaFormat& media_format, |
| 233 int* channels_out, | 260 int* channels_out, |
| 234 int* sample_rate_out, | 261 int* sample_rate_out, |
| 235 int* sample_bits_out) { | 262 int* sample_bits_out) { |
| 236 // TODO(scherkus): might be handy to support NULL parameters. | 263 // TODO(scherkus): might be handy to support NULL parameters. |
| 237 std::string mime_type; | 264 std::string mime_type; |
| 238 return media_format.GetAsString(MediaFormat::kMimeType, &mime_type) && | 265 return media_format.GetAsString(MediaFormat::kMimeType, &mime_type) && |
| 239 media_format.GetAsInteger(MediaFormat::kChannels, channels_out) && | 266 media_format.GetAsInteger(MediaFormat::kChannels, channels_out) && |
| 240 media_format.GetAsInteger(MediaFormat::kSampleRate, sample_rate_out) && | 267 media_format.GetAsInteger(MediaFormat::kSampleRate, sample_rate_out) && |
| 241 media_format.GetAsInteger(MediaFormat::kSampleBits, sample_bits_out) && | 268 media_format.GetAsInteger(MediaFormat::kSampleBits, sample_bits_out) && |
| 242 mime_type.compare(mime_type::kUncompressedAudio) == 0; | 269 mime_type.compare(mime_type::kUncompressedAudio) == 0; |
| 243 } | 270 } |
| 244 | 271 |
| 245 } // namespace media | 272 } // namespace media |
| OLD | NEW |