cros: Don't check consume kiosk flag for enterprise managed device.
[chromium-blink-merge.git] / media / base / audio_splicer.cc
blobe78cd2ba6af35adcc10a505d9878f90b18088f9f
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
3 // found in the LICENSE file.
5 #include "media/base/audio_splicer.h"
7 #include <cstdlib>
9 #include "base/logging.h"
10 #include "media/base/audio_decoder_config.h"
11 #include "media/base/audio_timestamp_helper.h"
12 #include "media/base/buffers.h"
13 #include "media/base/data_buffer.h"
15 namespace media {
17 // Largest gap or overlap allowed by this class. Anything
18 // larger than this will trigger an error.
19 // This is an arbitrary value, but the initial selection of 50ms
20 // roughly represents the duration of 2 compressed AAC or MP3 frames.
21 static const int kMaxTimeDeltaInMilliseconds = 50;
23 AudioSplicer::AudioSplicer(int bytes_per_frame, int samples_per_second)
24 : output_timestamp_helper_(bytes_per_frame, samples_per_second),
25 min_gap_size_(2 * bytes_per_frame),
26 received_end_of_stream_(false) {
29 AudioSplicer::~AudioSplicer() {
32 void AudioSplicer::Reset() {
33 output_timestamp_helper_.SetBaseTimestamp(kNoTimestamp());
34 output_buffers_.clear();
35 received_end_of_stream_ = false;
38 bool AudioSplicer::AddInput(const scoped_refptr<DataBuffer>& input){
39 DCHECK(!received_end_of_stream_ || input->IsEndOfStream());
41 if (input->IsEndOfStream()) {
42 output_buffers_.push_back(input);
43 received_end_of_stream_ = true;
44 return true;
47 DCHECK(input->GetTimestamp() != kNoTimestamp());
48 DCHECK(input->GetDuration() > base::TimeDelta());
49 DCHECK_GT(input->GetDataSize(), 0);
51 if (output_timestamp_helper_.base_timestamp() == kNoTimestamp())
52 output_timestamp_helper_.SetBaseTimestamp(input->GetTimestamp());
54 if (output_timestamp_helper_.base_timestamp() > input->GetTimestamp()) {
55 DVLOG(1) << "Input timestamp is before the base timestamp.";
56 return false;
59 base::TimeDelta timestamp = input->GetTimestamp();
60 base::TimeDelta expected_timestamp = output_timestamp_helper_.GetTimestamp();
61 base::TimeDelta delta = timestamp - expected_timestamp;
63 if (std::abs(delta.InMilliseconds()) > kMaxTimeDeltaInMilliseconds) {
64 DVLOG(1) << "Timestamp delta too large: " << delta.InMicroseconds() << "us";
65 return false;
68 int bytes_to_fill = 0;
69 if (delta != base::TimeDelta())
70 bytes_to_fill = output_timestamp_helper_.GetBytesToTarget(timestamp);
72 if (bytes_to_fill == 0 || std::abs(bytes_to_fill) < min_gap_size_) {
73 AddOutputBuffer(input);
74 return true;
77 if (bytes_to_fill > 0) {
78 DVLOG(1) << "Gap detected @ " << expected_timestamp.InMicroseconds()
79 << " us: " << delta.InMicroseconds() << " us";
81 // Create a buffer with enough silence samples to fill the gap and
82 // add it to the output buffer.
83 scoped_refptr<DataBuffer> gap = new DataBuffer(bytes_to_fill);
84 gap->SetDataSize(bytes_to_fill);
85 memset(gap->GetWritableData(), 0, bytes_to_fill);
86 gap->SetTimestamp(expected_timestamp);
87 gap->SetDuration(output_timestamp_helper_.GetDuration(bytes_to_fill));
88 AddOutputBuffer(gap);
90 // Add the input buffer now that the gap has been filled.
91 AddOutputBuffer(input);
92 return true;
95 int bytes_to_skip = -bytes_to_fill;
97 DVLOG(1) << "Overlap detected @ " << expected_timestamp.InMicroseconds()
98 << " us: " << -delta.InMicroseconds() << " us";
100 if (input->GetDataSize() <= bytes_to_skip) {
101 DVLOG(1) << "Dropping whole buffer";
102 return true;
105 // Copy the trailing samples that do not overlap samples already output
106 // into a new buffer. Add this new buffer to the output queue.
108 // TODO(acolwell): Implement a cross-fade here so the transition is less
109 // jarring.
110 int new_buffer_size = input->GetDataSize() - bytes_to_skip;
112 scoped_refptr<DataBuffer> new_buffer = new DataBuffer(new_buffer_size);
113 new_buffer->SetDataSize(new_buffer_size);
114 memcpy(new_buffer->GetWritableData(),
115 input->GetData() + bytes_to_skip,
116 new_buffer_size);
117 new_buffer->SetTimestamp(expected_timestamp);
118 new_buffer->SetDuration(
119 output_timestamp_helper_.GetDuration(new_buffer_size));
120 AddOutputBuffer(new_buffer);
121 return true;
124 bool AudioSplicer::HasNextBuffer() const {
125 return !output_buffers_.empty();
128 scoped_refptr<DataBuffer> AudioSplicer::GetNextBuffer() {
129 scoped_refptr<DataBuffer> ret = output_buffers_.front();
130 output_buffers_.pop_front();
131 return ret;
134 void AudioSplicer::AddOutputBuffer(const scoped_refptr<DataBuffer>& buffer) {
135 output_timestamp_helper_.AddBytes(buffer->GetDataSize());
136 output_buffers_.push_back(buffer);
139 } // namespace media