| 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 <cstdlib> | 7 #include <cstdlib> |
| 8 #include <deque> | 8 #include <deque> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "media/base/audio_buffer.h" | 11 #include "media/base/audio_buffer.h" |
| 12 #include "media/base/audio_bus.h" | 12 #include "media/base/audio_bus.h" |
| 13 #include "media/base/audio_decoder_config.h" | 13 #include "media/base/audio_decoder_config.h" |
| 14 #include "media/base/audio_timestamp_helper.h" | 14 #include "media/base/audio_timestamp_helper.h" |
| 15 #include "media/base/vector_math.h" | 15 #include "media/base/vector_math.h" |
| 16 | 16 |
| 17 namespace media { | 17 namespace media { |
| 18 | 18 |
| 19 // Largest gap or overlap allowed by this class. Anything | |
| 20 // larger than this will trigger an error. | |
| 21 // This is an arbitrary value, but the initial selection of 50ms | |
| 22 // roughly represents the duration of 2 compressed AAC or MP3 frames. | |
| 23 static const int kMaxTimeDeltaInMilliseconds = 50; | |
| 24 | |
| 25 // Minimum gap size needed before the splicer will take action to | 19 // Minimum gap size needed before the splicer will take action to |
| 26 // fill a gap. This avoids periodically inserting and then dropping samples | 20 // fill a gap. This avoids periodically inserting and then dropping samples |
| 27 // when the buffer timestamps are slightly off because of timestamp rounding | 21 // when the buffer timestamps are slightly off because of timestamp rounding |
| 28 // in the source content. Unit is frames. | 22 // in the source content. Unit is frames. |
| 29 static const int kMinGapSize = 2; | 23 static const int kMinGapSize = 2; |
| 30 | 24 |
| 31 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so | 25 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so |
| 32 // manually adjust the duration and timestamp after trimming. | 26 // manually adjust the duration and timestamp after trimming. |
| 33 static void AccurateTrimStart(int frames_to_trim, | 27 static void AccurateTrimStart(int frames_to_trim, |
| 34 const scoped_refptr<AudioBuffer> buffer, | 28 const scoped_refptr<AudioBuffer> buffer, |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 if (output_timestamp_helper_.base_timestamp() > input->timestamp()) { | 130 if (output_timestamp_helper_.base_timestamp() > input->timestamp()) { |
| 137 DVLOG(1) << "Input timestamp is before the base timestamp."; | 131 DVLOG(1) << "Input timestamp is before the base timestamp."; |
| 138 return false; | 132 return false; |
| 139 } | 133 } |
| 140 | 134 |
| 141 const base::TimeDelta timestamp = input->timestamp(); | 135 const base::TimeDelta timestamp = input->timestamp(); |
| 142 const base::TimeDelta expected_timestamp = | 136 const base::TimeDelta expected_timestamp = |
| 143 output_timestamp_helper_.GetTimestamp(); | 137 output_timestamp_helper_.GetTimestamp(); |
| 144 const base::TimeDelta delta = timestamp - expected_timestamp; | 138 const base::TimeDelta delta = timestamp - expected_timestamp; |
| 145 | 139 |
| 146 if (std::abs(delta.InMilliseconds()) > kMaxTimeDeltaInMilliseconds) { | 140 if (std::abs(delta.InMilliseconds()) > |
| 141 AudioSplicer::kMaxTimeDeltaInMilliseconds) { |
| 147 DVLOG(1) << "Timestamp delta too large: " << delta.InMicroseconds() << "us"; | 142 DVLOG(1) << "Timestamp delta too large: " << delta.InMicroseconds() << "us"; |
| 148 return false; | 143 return false; |
| 149 } | 144 } |
| 150 | 145 |
| 151 int frames_to_fill = 0; | 146 int frames_to_fill = 0; |
| 152 if (delta != base::TimeDelta()) | 147 if (delta != base::TimeDelta()) |
| 153 frames_to_fill = output_timestamp_helper_.GetFramesToTarget(timestamp); | 148 frames_to_fill = output_timestamp_helper_.GetFramesToTarget(timestamp); |
| 154 | 149 |
| 155 if (frames_to_fill == 0 || std::abs(frames_to_fill) < kMinGapSize) { | 150 if (frames_to_fill == 0 || std::abs(frames_to_fill) < kMinGapSize) { |
| 156 AddOutputBuffer(input); | 151 AddOutputBuffer(input); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 output_sanitizer_->ResetTimestampState( | 298 output_sanitizer_->ResetTimestampState( |
| 304 0, pre_splice_sanitizer_->timestamp_helper().base_timestamp()); | 299 0, pre_splice_sanitizer_->timestamp_helper().base_timestamp()); |
| 305 } | 300 } |
| 306 | 301 |
| 307 // If a splice frame was incorrectly marked due to poor demuxed timestamps, we | 302 // If a splice frame was incorrectly marked due to poor demuxed timestamps, we |
| 308 // may not actually have a splice. Here we check if any frames exist before | 303 // may not actually have a splice. Here we check if any frames exist before |
| 309 // the splice. In this case, just transfer all data to the output sanitizer. | 304 // the splice. In this case, just transfer all data to the output sanitizer. |
| 310 if (pre_splice_sanitizer_->GetFrameCount() <= | 305 if (pre_splice_sanitizer_->GetFrameCount() <= |
| 311 output_ts_helper.GetFramesToTarget(splice_timestamp_)) { | 306 output_ts_helper.GetFramesToTarget(splice_timestamp_)) { |
| 312 CHECK(pre_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 307 CHECK(pre_splice_sanitizer_->DrainInto(output_sanitizer_.get())); |
| 313 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 308 |
| 309 // If the file contains incorrectly muxed timestamps, there may be huge gaps |
| 310 // between the demuxed and decoded timestamps. |
| 311 if (!post_splice_sanitizer_->DrainInto(output_sanitizer_.get())) |
| 312 return false; |
| 313 |
| 314 reset_splice_timestamps(); | 314 reset_splice_timestamps(); |
| 315 return true; | 315 return true; |
| 316 } | 316 } |
| 317 | 317 |
| 318 // Wait until we have enough data to crossfade or end of stream. | 318 // Wait until we have enough data to crossfade or end of stream. |
| 319 if (!input->end_of_stream() && | 319 if (!input->end_of_stream() && |
| 320 input->timestamp() + input->duration() < max_splice_end_timestamp_) { | 320 input->timestamp() + input->duration() < max_splice_end_timestamp_) { |
| 321 return true; | 321 return true; |
| 322 } | 322 } |
| 323 | 323 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); | 498 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); |
| 499 CHECK(output_sanitizer_->AddInput(remainder)); | 499 CHECK(output_sanitizer_->AddInput(remainder)); |
| 500 } | 500 } |
| 501 | 501 |
| 502 // Transfer all remaining buffers out and reset once empty. | 502 // Transfer all remaining buffers out and reset once empty. |
| 503 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 503 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); |
| 504 post_splice_sanitizer_->Reset(); | 504 post_splice_sanitizer_->Reset(); |
| 505 } | 505 } |
| 506 | 506 |
| 507 } // namespace media | 507 } // namespace media |
| OLD | NEW |