OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/base/audio_discard_helper.h" | |
6 | |
7 #include <cmath> | |
8 | |
9 #include "base/logging.h" | |
10 #include "media/base/audio_buffer.h" | |
11 #include "media/base/buffers.h" | |
12 #include "media/base/decoder_buffer.h" | |
13 | |
14 namespace media { | |
15 | |
16 static void WarnOnNonMonotonicTimestamps(base::TimeDelta last_timestamp, | |
17 base::TimeDelta current_timestamp) { | |
18 if (last_timestamp == kNoTimestamp() || last_timestamp < current_timestamp) | |
19 return; | |
20 | |
21 const base::TimeDelta diff = current_timestamp - last_timestamp; | |
22 DLOG(WARNING) << "Input timestamps are not monotonically increasing! " | |
23 << " ts " << current_timestamp.InMicroseconds() << " us" | |
24 << " diff " << diff.InMicroseconds() << " us"; | |
25 } | |
26 | |
27 AudioDiscardHelper::AudioDiscardHelper(int sample_rate) | |
28 : sample_rate_(sample_rate), | |
29 timestamp_helper_(sample_rate_), | |
30 discard_frames_(0), | |
31 last_input_timestamp_(kNoTimestamp()) { | |
wolenetz
2014/04/28 21:52:07
nit: is any sanity checking needed on sample_rate_
DaleCurtis
2014/04/28 23:09:03
As far as this code is concerned it just needs to
| |
32 } | |
33 | |
34 AudioDiscardHelper::~AudioDiscardHelper() { | |
35 } | |
36 | |
37 int AudioDiscardHelper::TimeDeltaToFrames(base::TimeDelta duration) const { | |
38 DCHECK(duration >= base::TimeDelta()); | |
39 return std::ceil(duration.InSecondsF() * sample_rate_); | |
wolenetz
2014/04/28 21:52:07
With ceil(), might we hit off-by-one stuff here? (
DaleCurtis
2014/04/28 23:09:03
Since this floating point value is calculated from
| |
40 } | |
41 | |
42 void AudioDiscardHelper::Reset(size_t initial_discard) { | |
43 discard_frames_ = initial_discard; | |
44 last_input_timestamp_ = kNoTimestamp(); | |
45 timestamp_helper_.SetBaseTimestamp(kNoTimestamp()); | |
46 } | |
47 | |
48 bool AudioDiscardHelper::ProcessBuffers( | |
49 const scoped_refptr<DecoderBuffer>& encoded_buffer, | |
50 const scoped_refptr<AudioBuffer>& decoded_buffer) { | |
51 DCHECK(!encoded_buffer->end_of_stream()); | |
52 DCHECK(encoded_buffer->timestamp() != kNoTimestamp()); | |
53 | |
54 // Issue a debug warning when we see non-monotonic timestamps. Only a warning | |
55 // to allow chained OGG playback. | |
56 WarnOnNonMonotonicTimestamps(last_input_timestamp_, | |
57 encoded_buffer->timestamp()); | |
58 last_input_timestamp_ = encoded_buffer->timestamp(); | |
59 | |
60 // If this is the first buffer seen, setup the timestamp helper. | |
61 if (!initialized()) | |
62 timestamp_helper_.SetBaseTimestamp(encoded_buffer->timestamp()); | |
63 DCHECK(initialized()); | |
64 | |
65 if (!decoded_buffer || !decoded_buffer->frame_count()) | |
66 return false; | |
67 | |
68 if (discard_frames_ > 0) { | |
69 const size_t decoded_frames = decoded_buffer->frame_count(); | |
70 const size_t frames_to_discard = std::min(discard_frames_, decoded_frames); | |
71 discard_frames_ -= frames_to_discard; | |
72 | |
73 // If everything would be discarded, indicate a new buffer is required. | |
74 if (frames_to_discard == decoded_frames) | |
75 return false; | |
76 | |
77 decoded_buffer->TrimStart(frames_to_discard); | |
wolenetz
2014/04/28 21:52:07
TrimStart() will modify decoded_buffer's duration_
DaleCurtis
2014/04/28 22:03:51
It's this codes expectation that it is the sole au
wolenetz
2014/04/28 22:37:56
Regarding assumption of ability to set duration/ti
DaleCurtis
2014/04/28 23:09:03
I think that comment can be removed now. I'll do
| |
78 } | |
79 | |
80 // TODO(dalecurtis): Applying the current buffer's discard padding doesn't | |
81 // make sense in the Vorbis case because there is a delay of one buffer before | |
82 // decoded buffers are returned. Fix and add support for more than just end | |
83 // trimming. | |
wolenetz
2014/04/28 21:52:07
nit: reference bug?
DaleCurtis
2014/04/28 23:09:03
Done.
| |
84 if (encoded_buffer->discard_padding() > base::TimeDelta()) { | |
85 const size_t decoded_frames = decoded_buffer->frame_count(); | |
86 const size_t end_frames_to_discard = | |
87 TimeDeltaToFrames(encoded_buffer->discard_padding()); | |
88 if (end_frames_to_discard > decoded_frames) { | |
wolenetz
2014/04/28 21:52:07
Is end discard aware of start discard? (If not, co
DaleCurtis
2014/04/28 22:03:51
It's expected that users of discard_padding() will
| |
89 DLOG(ERROR) << "Invalid file. Incorrect discard padding value."; | |
wolenetz
2014/04/28 21:52:07
nit: If this helper will be used by MSE, not just
DaleCurtis
2014/04/28 23:09:03
Done.
| |
90 return false; | |
91 } | |
92 | |
93 // If everything would be discarded, indicate a new buffer is required. | |
94 if (end_frames_to_discard == decoded_frames) | |
95 return false; | |
96 | |
97 decoded_buffer->TrimEnd(end_frames_to_discard); | |
98 } else { | |
99 DCHECK(encoded_buffer->discard_padding() == base::TimeDelta()); | |
100 } | |
101 | |
102 // Assign timestamp and duration to the buffer. | |
103 decoded_buffer->set_timestamp(timestamp_helper_.GetTimestamp()); | |
104 decoded_buffer->set_duration( | |
105 timestamp_helper_.GetFrameDuration(decoded_buffer->frame_count())); | |
106 timestamp_helper_.AddFrames(decoded_buffer->frame_count()); | |
107 return true; | |
108 } | |
109 | |
110 } // namespace media | |
OLD | NEW |