OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_discard_helper.h" | 5 #include "media/base/audio_discard_helper.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "media/base/audio_buffer.h" | 10 #include "media/base/audio_buffer.h" |
11 | 11 |
12 namespace media { | 12 namespace media { |
13 | 13 |
14 static void WarnOnNonMonotonicTimestamps(base::TimeDelta last_timestamp, | 14 static void WarnOnNonMonotonicTimestamps(base::TimeDelta last_timestamp, |
15 base::TimeDelta current_timestamp) { | 15 base::TimeDelta current_timestamp) { |
16 if (last_timestamp == kNoTimestamp || last_timestamp < current_timestamp) | 16 if (last_timestamp == kNoTimestamp || last_timestamp < current_timestamp) |
17 return; | 17 return; |
18 | 18 |
19 const base::TimeDelta diff = current_timestamp - last_timestamp; | 19 const base::TimeDelta diff = current_timestamp - last_timestamp; |
20 DLOG(WARNING) << "Input timestamps are not monotonically increasing! " | 20 DLOG(WARNING) << "Input timestamps are not monotonically increasing! " |
21 << " ts " << current_timestamp.InMicroseconds() << " us" | 21 << " ts " << current_timestamp.InMicroseconds() << " us" |
22 << " diff " << diff.InMicroseconds() << " us"; | 22 << " diff " << diff.InMicroseconds() << " us"; |
23 } | 23 } |
24 | 24 |
25 AudioDiscardHelper::AudioDiscardHelper(int sample_rate, size_t decoder_delay) | 25 AudioDiscardHelper::AudioDiscardHelper(int sample_rate, |
| 26 size_t decoder_delay, |
| 27 bool delayed_discard) |
26 : sample_rate_(sample_rate), | 28 : sample_rate_(sample_rate), |
27 decoder_delay_(decoder_delay), | 29 decoder_delay_(decoder_delay), |
28 timestamp_helper_(sample_rate_), | 30 timestamp_helper_(sample_rate_), |
29 discard_frames_(0), | 31 discard_frames_(0), |
30 last_input_timestamp_(kNoTimestamp), | 32 last_input_timestamp_(kNoTimestamp), |
31 delayed_discard_(false), | 33 delayed_discard_(delayed_discard), |
32 delayed_end_discard_(0) { | 34 delayed_end_discard_(0) { |
33 DCHECK_GT(sample_rate_, 0); | 35 DCHECK_GT(sample_rate_, 0); |
34 } | 36 } |
35 | 37 |
36 AudioDiscardHelper::~AudioDiscardHelper() { | 38 AudioDiscardHelper::~AudioDiscardHelper() { |
37 } | 39 } |
38 | 40 |
39 size_t AudioDiscardHelper::TimeDeltaToFrames(base::TimeDelta duration) const { | 41 size_t AudioDiscardHelper::TimeDeltaToFrames(base::TimeDelta duration) const { |
40 DCHECK(duration >= base::TimeDelta()); | 42 DCHECK(duration >= base::TimeDelta()); |
41 return duration.InSecondsF() * sample_rate_ + 0.5; | 43 return duration.InSecondsF() * sample_rate_ + 0.5; |
42 } | 44 } |
43 | 45 |
44 void AudioDiscardHelper::Reset(size_t initial_discard) { | 46 void AudioDiscardHelper::Reset(size_t initial_discard) { |
45 discard_frames_ = initial_discard; | 47 discard_frames_ = initial_discard; |
46 last_input_timestamp_ = kNoTimestamp; | 48 last_input_timestamp_ = kNoTimestamp; |
47 timestamp_helper_.SetBaseTimestamp(kNoTimestamp); | 49 timestamp_helper_.SetBaseTimestamp(kNoTimestamp); |
48 delayed_discard_ = false; | |
49 delayed_discard_padding_ = DecoderBuffer::DiscardPadding(); | 50 delayed_discard_padding_ = DecoderBuffer::DiscardPadding(); |
50 } | 51 } |
51 | 52 |
52 bool AudioDiscardHelper::ProcessBuffers( | 53 bool AudioDiscardHelper::ProcessBuffers( |
53 const scoped_refptr<DecoderBuffer>& encoded_buffer, | 54 const scoped_refptr<DecoderBuffer>& encoded_buffer, |
54 const scoped_refptr<AudioBuffer>& decoded_buffer) { | 55 const scoped_refptr<AudioBuffer>& decoded_buffer) { |
55 DCHECK(!encoded_buffer->end_of_stream()); | 56 DCHECK(!encoded_buffer->end_of_stream()); |
56 DCHECK(encoded_buffer->timestamp() != kNoTimestamp); | 57 DCHECK(encoded_buffer->timestamp() != kNoTimestamp); |
57 | 58 |
58 // Issue a debug warning when we see non-monotonic timestamps. Only a warning | 59 // Issue a debug warning when we see non-monotonic timestamps. Only a warning |
59 // to allow chained OGG playback. | 60 // to allow chained OGG playback. |
60 WarnOnNonMonotonicTimestamps(last_input_timestamp_, | 61 WarnOnNonMonotonicTimestamps(last_input_timestamp_, |
61 encoded_buffer->timestamp()); | 62 encoded_buffer->timestamp()); |
62 last_input_timestamp_ = encoded_buffer->timestamp(); | 63 last_input_timestamp_ = encoded_buffer->timestamp(); |
63 | 64 |
64 // If this is the first buffer seen, setup the timestamp helper. | 65 // If this is the first buffer seen, setup the timestamp helper. |
65 const bool first_buffer = !initialized(); | 66 if (!initialized()) { |
66 if (first_buffer) { | |
67 // Clamp the base timestamp to zero. | 67 // Clamp the base timestamp to zero. |
68 timestamp_helper_.SetBaseTimestamp( | 68 timestamp_helper_.SetBaseTimestamp( |
69 std::max(base::TimeDelta(), encoded_buffer->timestamp())); | 69 std::max(base::TimeDelta(), encoded_buffer->timestamp())); |
70 } | 70 } |
71 DCHECK(initialized()); | 71 DCHECK(initialized()); |
72 | 72 |
73 if (!decoded_buffer.get()) { | 73 if (!decoded_buffer.get()) { |
74 // If there's a one buffer delay for decoding, we need to save it so it can | 74 // If there's a one buffer delay for decoding, we need to save it so it can |
75 // be processed with the next decoder buffer. | 75 // be processed with the next decoder buffer. |
76 if (first_buffer) { | 76 if (delayed_discard_) |
77 delayed_discard_ = true; | |
78 delayed_discard_padding_ = encoded_buffer->discard_padding(); | 77 delayed_discard_padding_ = encoded_buffer->discard_padding(); |
79 } | |
80 return false; | 78 return false; |
81 } | 79 } |
82 | 80 |
83 const size_t original_frame_count = decoded_buffer->frame_count(); | 81 const size_t original_frame_count = decoded_buffer->frame_count(); |
84 | 82 |
85 // If there's a one buffer delay for decoding, pick up the last encoded | 83 // If there's a one buffer delay for decoding, pick up the last encoded |
86 // buffer's discard padding for processing with the current decoded buffer. | 84 // buffer's discard padding for processing with the current decoded buffer. |
87 DecoderBuffer::DiscardPadding current_discard_padding = | 85 DecoderBuffer::DiscardPadding current_discard_padding = |
88 encoded_buffer->discard_padding(); | 86 encoded_buffer->discard_padding(); |
89 if (delayed_discard_) { | 87 if (delayed_discard_) { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 DVLOG(3) << __func__ << " ts: " << timestamp_helper_.GetTimestamp() | 230 DVLOG(3) << __func__ << " ts: " << timestamp_helper_.GetTimestamp() |
233 << " frames: " << decoded_buffer->frame_count(); | 231 << " frames: " << decoded_buffer->frame_count(); |
234 | 232 |
235 // Assign timestamp to the buffer. | 233 // Assign timestamp to the buffer. |
236 decoded_buffer->set_timestamp(timestamp_helper_.GetTimestamp()); | 234 decoded_buffer->set_timestamp(timestamp_helper_.GetTimestamp()); |
237 timestamp_helper_.AddFrames(decoded_buffer->frame_count()); | 235 timestamp_helper_.AddFrames(decoded_buffer->frame_count()); |
238 return true; | 236 return true; |
239 } | 237 } |
240 | 238 |
241 } // namespace media | 239 } // namespace media |
OLD | NEW |