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 |