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 |