1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/audio_discard_helper.h"
#include <algorithm>
#include "base/logging.h"
#include "media/base/audio_buffer.h"
#include "media/base/buffers.h"
#include "media/base/decoder_buffer.h"
namespace media {
static void WarnOnNonMonotonicTimestamps(base::TimeDelta last_timestamp,
base::TimeDelta current_timestamp) {
if (last_timestamp == kNoTimestamp() || last_timestamp < current_timestamp)
return;
const base::TimeDelta diff = current_timestamp - last_timestamp;
DLOG(WARNING) << "Input timestamps are not monotonically increasing! "
<< " ts " << current_timestamp.InMicroseconds() << " us"
<< " diff " << diff.InMicroseconds() << " us";
}
AudioDiscardHelper::AudioDiscardHelper(int sample_rate)
: sample_rate_(sample_rate),
timestamp_helper_(sample_rate_),
discard_frames_(0),
last_input_timestamp_(kNoTimestamp()) {
DCHECK_GT(sample_rate_, 0);
}
AudioDiscardHelper::~AudioDiscardHelper() {
}
size_t AudioDiscardHelper::TimeDeltaToFrames(base::TimeDelta duration) const {
DCHECK(duration >= base::TimeDelta());
return duration.InSecondsF() * sample_rate_ + 0.5;
}
void AudioDiscardHelper::Reset(size_t initial_discard) {
discard_frames_ = initial_discard;
last_input_timestamp_ = kNoTimestamp();
timestamp_helper_.SetBaseTimestamp(kNoTimestamp());
}
bool AudioDiscardHelper::ProcessBuffers(
const scoped_refptr<DecoderBuffer>& encoded_buffer,
const scoped_refptr<AudioBuffer>& decoded_buffer) {
DCHECK(!encoded_buffer->end_of_stream());
DCHECK(encoded_buffer->timestamp() != kNoTimestamp());
// Issue a debug warning when we see non-monotonic timestamps. Only a warning
// to allow chained OGG playback.
WarnOnNonMonotonicTimestamps(last_input_timestamp_,
encoded_buffer->timestamp());
last_input_timestamp_ = encoded_buffer->timestamp();
// If this is the first buffer seen, setup the timestamp helper.
if (!initialized()) {
// Clamp the base timestamp to zero.
timestamp_helper_.SetBaseTimestamp(
std::max(base::TimeDelta(), encoded_buffer->timestamp()));
}
DCHECK(initialized());
if (!decoded_buffer || !decoded_buffer->frame_count())
return false;
if (discard_frames_ > 0) {
const size_t decoded_frames = decoded_buffer->frame_count();
const size_t frames_to_discard = std::min(discard_frames_, decoded_frames);
discard_frames_ -= frames_to_discard;
// If everything would be discarded, indicate a new buffer is required.
if (frames_to_discard == decoded_frames)
return false;
decoded_buffer->TrimStart(frames_to_discard);
}
// TODO(dalecurtis): Applying the current buffer's discard padding doesn't
// make sense in the Vorbis case because there is a delay of one buffer before
// decoded buffers are returned. Fix and add support for more than just end
// trimming. See http://crbug.com/360961.
if (encoded_buffer->discard_padding() > base::TimeDelta()) {
const size_t decoded_frames = decoded_buffer->frame_count();
const size_t end_frames_to_discard =
TimeDeltaToFrames(encoded_buffer->discard_padding());
if (end_frames_to_discard > decoded_frames) {
DLOG(ERROR) << "Encountered invalid discard padding value.";
return false;
}
// If everything would be discarded, indicate a new buffer is required.
if (end_frames_to_discard == decoded_frames)
return false;
decoded_buffer->TrimEnd(end_frames_to_discard);
} else {
DCHECK(encoded_buffer->discard_padding() == base::TimeDelta());
}
// Assign timestamp and duration to the buffer.
decoded_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
decoded_buffer->set_duration(
timestamp_helper_.GetFrameDuration(decoded_buffer->frame_count()));
timestamp_helper_.AddFrames(decoded_buffer->frame_count());
return true;
}
} // namespace media
|