This is jamesr@ code I am landing.
[chromium-blink-merge.git] / media / base / audio_splicer.h
blob0db5d08dd70b7c8e49b5bc0650b57f5d78edb51f
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 #ifndef MEDIA_BASE_AUDIO_SPLICER_H_
6 #define MEDIA_BASE_AUDIO_SPLICER_H_
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/time/time.h"
11 #include "media/audio/audio_parameters.h"
12 #include "media/base/buffers.h"
13 #include "media/base/media_export.h"
15 namespace media {
17 class AudioBuffer;
18 class AudioBus;
19 class AudioStreamSanitizer;
21 // Helper class that handles filling gaps and resolving overlaps.
22 class MEDIA_EXPORT AudioSplicer {
23 public:
24 explicit AudioSplicer(int samples_per_second);
25 ~AudioSplicer();
27 enum {
28 // The number of ms to crossfade before trimming when buffers overlap.
29 kCrossfadeDurationInMilliseconds = 5,
31 // Largest gap or overlap allowed between buffers. Anything larger than
32 // this will trigger an error. This is an arbitrary value, but the initial
33 // selection of 50ms roughly represents the duration of 2 compressed AAC or
34 // MP3 frames.
35 kMaxTimeDeltaInMilliseconds = 50,
38 // Resets the splicer state by clearing the output buffers queue and resetting
39 // the timestamp helper.
40 void Reset();
42 // Adds a new buffer full of samples or end of stream buffer to the splicer.
43 // Returns true if the buffer was accepted. False is returned if an error
44 // occurred.
45 bool AddInput(const scoped_refptr<AudioBuffer>& input);
47 // Returns true if the splicer has a buffer to return.
48 bool HasNextBuffer() const;
50 // Removes the next buffer from the output buffer queue and returns it; this
51 // should only be called if HasNextBuffer() returns true.
52 scoped_refptr<AudioBuffer> GetNextBuffer();
54 // Indicates an upcoming splice point. All buffers overlapping or after the
55 // |splice_timestamp| will be considered as "before the splice." Clients must
56 // then call SetSpliceTimestamp(kNoTimestamp()) to signal that future buffers
57 // should be considered as "after the splice."
59 // Once |kCrossfadeDurationInMilliseconds| of buffers "after the splice" or
60 // end of stream has been received, the "after" buffers will be crossfaded
61 // with all "before" buffers which overlap them. "before" buffers outside
62 // of the overlap range will be discarded.
63 void SetSpliceTimestamp(base::TimeDelta splice_timestamp);
65 private:
66 friend class AudioSplicerTest;
68 // Extracts frames to be crossfaded from |pre_splice_sanitizer_|. Transfers
69 // all frames before |splice_timestamp_| into |output_sanitizer_| and drops
70 // frames outside of the crossfade duration.
72 // The size of the returned AudioBus is the crossfade duration in frames.
73 // Crossfade duration is calculated based on the number of frames available
74 // after |splice_timestamp_| in each sanitizer and capped by
75 // |max_crossfade_duration_|.
77 // |pre_splice_sanitizer_| will be empty after this operation.
78 scoped_ptr<AudioBus> ExtractCrossfadeFromPreSplice(
79 scoped_refptr<AudioBuffer>* crossfade_buffer);
81 // Crossfades |pre_splice_bus->frames()| frames from
82 // |post_splice_sanitizer_|
83 // with those from |pre_splice_bus|. Adds the crossfaded buffer to
84 // |output_sanitizer_| along with all buffers in |post_splice_sanitizer_|.
86 // |post_splice_sanitizer_| will be empty after this operation.
87 void CrossfadePostSplice(scoped_ptr<AudioBus> pre_splice_bus,
88 scoped_refptr<AudioBuffer> crossfade_buffer);
90 // Reset the splice and splice end timestamps.
91 void reset_splice_timestamps() {
92 splice_timestamp_ = max_splice_end_timestamp_ = kNoTimestamp();
95 const base::TimeDelta max_crossfade_duration_;
96 base::TimeDelta splice_timestamp_;
97 base::TimeDelta max_splice_end_timestamp_;
99 // The various sanitizers for each stage of the crossfade process. Buffers in
100 // |output_sanitizer_| are immediately available for consumption by external
101 // callers.
103 // Overlapped buffers go into the |pre_splice_sanitizer_| while overlapping
104 // buffers go into the |post_splice_sanitizer_|. Once enough buffers for
105 // crossfading are received the pre and post sanitizers are drained into
106 // |output_sanitizer_| by the two ExtractCrossfadeFromXXX methods above.
108 // |pre_splice_sanitizer_| is not constructed until the first splice frame is
109 // encountered. At which point it is constructed based on the timestamp state
110 // of |output_sanitizer_|. It is destructed once the splice is finished.
111 scoped_ptr<AudioStreamSanitizer> output_sanitizer_;
112 scoped_ptr<AudioStreamSanitizer> pre_splice_sanitizer_;
113 scoped_ptr<AudioStreamSanitizer> post_splice_sanitizer_;
115 // Whether all buffers which should go into |pre_splice_sanitizer_| have been
116 // received. If true, buffers should now be put in |post_splice_sanitizer_|.
117 bool have_all_pre_splice_buffers_;
119 DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSplicer);
122 } // namespace media
124 #endif