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