| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/audio_splicer.h" | 5 #include "media/base/audio_splicer.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <cstdlib> | 8 #include <cstdlib> |
| 9 #include <deque> | 9 #include <deque> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 }; | 117 }; |
| 118 | 118 |
| 119 AudioStreamSanitizer::AudioStreamSanitizer( | 119 AudioStreamSanitizer::AudioStreamSanitizer( |
| 120 int samples_per_second, | 120 int samples_per_second, |
| 121 const scoped_refptr<MediaLog>& media_log) | 121 const scoped_refptr<MediaLog>& media_log) |
| 122 : output_timestamp_helper_(samples_per_second), media_log_(media_log) {} | 122 : output_timestamp_helper_(samples_per_second), media_log_(media_log) {} |
| 123 | 123 |
| 124 AudioStreamSanitizer::~AudioStreamSanitizer() {} | 124 AudioStreamSanitizer::~AudioStreamSanitizer() {} |
| 125 | 125 |
| 126 void AudioStreamSanitizer::Reset() { | 126 void AudioStreamSanitizer::Reset() { |
| 127 ResetTimestampState(0, kNoTimestamp()); | 127 ResetTimestampState(0, kNoTimestamp); |
| 128 } | 128 } |
| 129 | 129 |
| 130 void AudioStreamSanitizer::ResetTimestampState(int64_t frame_count, | 130 void AudioStreamSanitizer::ResetTimestampState(int64_t frame_count, |
| 131 base::TimeDelta base_timestamp) { | 131 base::TimeDelta base_timestamp) { |
| 132 output_buffers_.clear(); | 132 output_buffers_.clear(); |
| 133 received_end_of_stream_ = false; | 133 received_end_of_stream_ = false; |
| 134 output_timestamp_helper_.SetBaseTimestamp(base_timestamp); | 134 output_timestamp_helper_.SetBaseTimestamp(base_timestamp); |
| 135 if (frame_count > 0) | 135 if (frame_count > 0) |
| 136 output_timestamp_helper_.AddFrames(frame_count); | 136 output_timestamp_helper_.AddFrames(frame_count); |
| 137 } | 137 } |
| 138 | 138 |
| 139 bool AudioStreamSanitizer::AddInput(const scoped_refptr<AudioBuffer>& input) { | 139 bool AudioStreamSanitizer::AddInput(const scoped_refptr<AudioBuffer>& input) { |
| 140 DCHECK(!received_end_of_stream_ || input->end_of_stream()); | 140 DCHECK(!received_end_of_stream_ || input->end_of_stream()); |
| 141 | 141 |
| 142 if (input->end_of_stream()) { | 142 if (input->end_of_stream()) { |
| 143 output_buffers_.push_back(input); | 143 output_buffers_.push_back(input); |
| 144 received_end_of_stream_ = true; | 144 received_end_of_stream_ = true; |
| 145 return true; | 145 return true; |
| 146 } | 146 } |
| 147 | 147 |
| 148 DCHECK(input->timestamp() != kNoTimestamp()); | 148 DCHECK(input->timestamp() != kNoTimestamp); |
| 149 DCHECK(input->duration() > base::TimeDelta()); | 149 DCHECK(input->duration() > base::TimeDelta()); |
| 150 DCHECK_GT(input->frame_count(), 0); | 150 DCHECK_GT(input->frame_count(), 0); |
| 151 | 151 |
| 152 if (output_timestamp_helper_.base_timestamp() == kNoTimestamp()) | 152 if (output_timestamp_helper_.base_timestamp() == kNoTimestamp) |
| 153 output_timestamp_helper_.SetBaseTimestamp(input->timestamp()); | 153 output_timestamp_helper_.SetBaseTimestamp(input->timestamp()); |
| 154 | 154 |
| 155 if (output_timestamp_helper_.base_timestamp() > input->timestamp()) { | 155 if (output_timestamp_helper_.base_timestamp() > input->timestamp()) { |
| 156 MEDIA_LOG(ERROR, media_log_) | 156 MEDIA_LOG(ERROR, media_log_) |
| 157 << "Audio splicing failed: unexpected timestamp sequence. base " | 157 << "Audio splicing failed: unexpected timestamp sequence. base " |
| 158 "timestamp=" | 158 "timestamp=" |
| 159 << output_timestamp_helper_.base_timestamp().InMicroseconds() | 159 << output_timestamp_helper_.base_timestamp().InMicroseconds() |
| 160 << "us, input timestamp=" << input->timestamp().InMicroseconds() | 160 << "us, input timestamp=" << input->timestamp().InMicroseconds() |
| 161 << "us"; | 161 << "us"; |
| 162 return false; | 162 return false; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 if (!output->AddInput(GetNextBuffer())) | 270 if (!output->AddInput(GetNextBuffer())) |
| 271 return false; | 271 return false; |
| 272 } | 272 } |
| 273 return true; | 273 return true; |
| 274 } | 274 } |
| 275 | 275 |
| 276 AudioSplicer::AudioSplicer(int samples_per_second, | 276 AudioSplicer::AudioSplicer(int samples_per_second, |
| 277 const scoped_refptr<MediaLog>& media_log) | 277 const scoped_refptr<MediaLog>& media_log) |
| 278 : max_crossfade_duration_( | 278 : max_crossfade_duration_( |
| 279 base::TimeDelta::FromMilliseconds(kCrossfadeDurationInMilliseconds)), | 279 base::TimeDelta::FromMilliseconds(kCrossfadeDurationInMilliseconds)), |
| 280 splice_timestamp_(kNoTimestamp()), | 280 splice_timestamp_(kNoTimestamp), |
| 281 max_splice_end_timestamp_(kNoTimestamp()), | 281 max_splice_end_timestamp_(kNoTimestamp), |
| 282 output_sanitizer_( | 282 output_sanitizer_( |
| 283 new AudioStreamSanitizer(samples_per_second, media_log)), | 283 new AudioStreamSanitizer(samples_per_second, media_log)), |
| 284 pre_splice_sanitizer_( | 284 pre_splice_sanitizer_( |
| 285 new AudioStreamSanitizer(samples_per_second, media_log)), | 285 new AudioStreamSanitizer(samples_per_second, media_log)), |
| 286 post_splice_sanitizer_( | 286 post_splice_sanitizer_( |
| 287 new AudioStreamSanitizer(samples_per_second, media_log)), | 287 new AudioStreamSanitizer(samples_per_second, media_log)), |
| 288 have_all_pre_splice_buffers_(false) { | 288 have_all_pre_splice_buffers_(false) {} |
| 289 } | |
| 290 | 289 |
| 291 AudioSplicer::~AudioSplicer() {} | 290 AudioSplicer::~AudioSplicer() {} |
| 292 | 291 |
| 293 void AudioSplicer::Reset() { | 292 void AudioSplicer::Reset() { |
| 294 output_sanitizer_->Reset(); | 293 output_sanitizer_->Reset(); |
| 295 pre_splice_sanitizer_->Reset(); | 294 pre_splice_sanitizer_->Reset(); |
| 296 post_splice_sanitizer_->Reset(); | 295 post_splice_sanitizer_->Reset(); |
| 297 have_all_pre_splice_buffers_ = false; | 296 have_all_pre_splice_buffers_ = false; |
| 298 reset_splice_timestamps(); | 297 reset_splice_timestamps(); |
| 299 } | 298 } |
| 300 | 299 |
| 301 bool AudioSplicer::AddInput(const scoped_refptr<AudioBuffer>& input) { | 300 bool AudioSplicer::AddInput(const scoped_refptr<AudioBuffer>& input) { |
| 302 // If we're not processing a splice, add the input to the output queue. | 301 // If we're not processing a splice, add the input to the output queue. |
| 303 if (splice_timestamp_ == kNoTimestamp()) { | 302 if (splice_timestamp_ == kNoTimestamp) { |
| 304 DCHECK(!pre_splice_sanitizer_->HasNextBuffer()); | 303 DCHECK(!pre_splice_sanitizer_->HasNextBuffer()); |
| 305 DCHECK(!post_splice_sanitizer_->HasNextBuffer()); | 304 DCHECK(!post_splice_sanitizer_->HasNextBuffer()); |
| 306 return output_sanitizer_->AddInput(input); | 305 return output_sanitizer_->AddInput(input); |
| 307 } | 306 } |
| 308 | 307 |
| 309 const AudioTimestampHelper& output_ts_helper = | 308 const AudioTimestampHelper& output_ts_helper = |
| 310 output_sanitizer_->timestamp_helper(); | 309 output_sanitizer_->timestamp_helper(); |
| 311 | 310 |
| 312 if (!have_all_pre_splice_buffers_) { | 311 if (!have_all_pre_splice_buffers_) { |
| 313 DCHECK(!input->end_of_stream()); | 312 DCHECK(!input->end_of_stream()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 336 CHECK(splice_timestamp_ == input->timestamp()); | 335 CHECK(splice_timestamp_ == input->timestamp()); |
| 337 | 336 |
| 338 // At this point we have all the fade out preroll buffers from the decoder. | 337 // At this point we have all the fade out preroll buffers from the decoder. |
| 339 // We now need to wait until we have enough data to perform the crossfade (or | 338 // We now need to wait until we have enough data to perform the crossfade (or |
| 340 // we receive an end of stream). | 339 // we receive an end of stream). |
| 341 if (!post_splice_sanitizer_->AddInput(input)) | 340 if (!post_splice_sanitizer_->AddInput(input)) |
| 342 return false; | 341 return false; |
| 343 | 342 |
| 344 // Ensure |output_sanitizer_| has a valid base timestamp so we can use it for | 343 // Ensure |output_sanitizer_| has a valid base timestamp so we can use it for |
| 345 // timestamp calculations. | 344 // timestamp calculations. |
| 346 if (output_ts_helper.base_timestamp() == kNoTimestamp()) { | 345 if (output_ts_helper.base_timestamp() == kNoTimestamp) { |
| 347 output_sanitizer_->ResetTimestampState( | 346 output_sanitizer_->ResetTimestampState( |
| 348 0, pre_splice_sanitizer_->timestamp_helper().base_timestamp()); | 347 0, pre_splice_sanitizer_->timestamp_helper().base_timestamp()); |
| 349 } | 348 } |
| 350 | 349 |
| 351 // If a splice frame was incorrectly marked due to poor demuxed timestamps, we | 350 // If a splice frame was incorrectly marked due to poor demuxed timestamps, we |
| 352 // may not actually have a splice. Here we check if any frames exist before | 351 // may not actually have a splice. Here we check if any frames exist before |
| 353 // the splice. In this case, just transfer all data to the output sanitizer. | 352 // the splice. In this case, just transfer all data to the output sanitizer. |
| 354 const int frames_before_splice = | 353 const int frames_before_splice = |
| 355 output_ts_helper.base_timestamp() == kNoTimestamp() | 354 output_ts_helper.base_timestamp() == kNoTimestamp |
| 356 ? 0 | 355 ? 0 |
| 357 : output_ts_helper.GetFramesToTarget(splice_timestamp_); | 356 : output_ts_helper.GetFramesToTarget(splice_timestamp_); |
| 358 if (frames_before_splice < 0 || | 357 if (frames_before_splice < 0 || |
| 359 pre_splice_sanitizer_->GetFrameCount() <= frames_before_splice) { | 358 pre_splice_sanitizer_->GetFrameCount() <= frames_before_splice) { |
| 360 CHECK(pre_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 359 CHECK(pre_splice_sanitizer_->DrainInto(output_sanitizer_.get())); |
| 361 | 360 |
| 362 // If the file contains incorrectly muxed timestamps, there may be huge gaps | 361 // If the file contains incorrectly muxed timestamps, there may be huge gaps |
| 363 // between the demuxed and decoded timestamps. | 362 // between the demuxed and decoded timestamps. |
| 364 if (!post_splice_sanitizer_->DrainInto(output_sanitizer_.get())) | 363 if (!post_splice_sanitizer_->DrainInto(output_sanitizer_.get())) |
| 365 return false; | 364 return false; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 389 | 388 |
| 390 bool AudioSplicer::HasNextBuffer() const { | 389 bool AudioSplicer::HasNextBuffer() const { |
| 391 return output_sanitizer_->HasNextBuffer(); | 390 return output_sanitizer_->HasNextBuffer(); |
| 392 } | 391 } |
| 393 | 392 |
| 394 scoped_refptr<AudioBuffer> AudioSplicer::GetNextBuffer() { | 393 scoped_refptr<AudioBuffer> AudioSplicer::GetNextBuffer() { |
| 395 return output_sanitizer_->GetNextBuffer(); | 394 return output_sanitizer_->GetNextBuffer(); |
| 396 } | 395 } |
| 397 | 396 |
| 398 void AudioSplicer::SetSpliceTimestamp(base::TimeDelta splice_timestamp) { | 397 void AudioSplicer::SetSpliceTimestamp(base::TimeDelta splice_timestamp) { |
| 399 if (splice_timestamp == kNoTimestamp()) { | 398 if (splice_timestamp == kNoTimestamp) { |
| 400 DCHECK(splice_timestamp_ != kNoTimestamp()); | 399 DCHECK(splice_timestamp_ != kNoTimestamp); |
| 401 DCHECK(!have_all_pre_splice_buffers_); | 400 DCHECK(!have_all_pre_splice_buffers_); |
| 402 have_all_pre_splice_buffers_ = true; | 401 have_all_pre_splice_buffers_ = true; |
| 403 return; | 402 return; |
| 404 } | 403 } |
| 405 | 404 |
| 406 if (splice_timestamp_ == splice_timestamp) | 405 if (splice_timestamp_ == splice_timestamp) |
| 407 return; | 406 return; |
| 408 | 407 |
| 409 // TODO(dalecurtis): We may need the concept of a future_splice_timestamp_ to | 408 // TODO(dalecurtis): We may need the concept of a future_splice_timestamp_ to |
| 410 // handle cases where another splice comes in before we've received 5ms of | 409 // handle cases where another splice comes in before we've received 5ms of |
| 411 // data from the last one. Leave this as a CHECK for now to figure out if | 410 // data from the last one. Leave this as a CHECK for now to figure out if |
| 412 // this case is possible. | 411 // this case is possible. |
| 413 CHECK(splice_timestamp_ == kNoTimestamp()); | 412 CHECK(splice_timestamp_ == kNoTimestamp); |
| 414 splice_timestamp_ = splice_timestamp; | 413 splice_timestamp_ = splice_timestamp; |
| 415 max_splice_end_timestamp_ = splice_timestamp_ + max_crossfade_duration_; | 414 max_splice_end_timestamp_ = splice_timestamp_ + max_crossfade_duration_; |
| 416 pre_splice_sanitizer_->Reset(); | 415 pre_splice_sanitizer_->Reset(); |
| 417 post_splice_sanitizer_->Reset(); | 416 post_splice_sanitizer_->Reset(); |
| 418 have_all_pre_splice_buffers_ = false; | 417 have_all_pre_splice_buffers_ = false; |
| 419 } | 418 } |
| 420 | 419 |
| 421 std::unique_ptr<AudioBus> AudioSplicer::ExtractCrossfadeFromPreSplice( | 420 std::unique_ptr<AudioBus> AudioSplicer::ExtractCrossfadeFromPreSplice( |
| 422 scoped_refptr<AudioBuffer>* crossfade_buffer) { | 421 scoped_refptr<AudioBuffer>* crossfade_buffer) { |
| 423 DCHECK(crossfade_buffer); | 422 DCHECK(crossfade_buffer); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); | 551 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); |
| 553 CHECK(output_sanitizer_->AddInput(remainder)); | 552 CHECK(output_sanitizer_->AddInput(remainder)); |
| 554 } | 553 } |
| 555 | 554 |
| 556 // Transfer all remaining buffers out and reset once empty. | 555 // Transfer all remaining buffers out and reset once empty. |
| 557 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 556 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); |
| 558 post_splice_sanitizer_->Reset(); | 557 post_splice_sanitizer_->Reset(); |
| 559 } | 558 } |
| 560 | 559 |
| 561 } // namespace media | 560 } // namespace media |
| OLD | NEW |