Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: webrtc/modules/audio_processing/utility/ring_buffer.cc

Issue 1858873003: Revert of Moved the ringbuffer to be built using C++ (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@MoveRingBuffer_CL
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/audio_processing/utility/ring_buffer.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 // A ring buffer to hold arbitrary data. Provides no thread safety. Unless
12 // otherwise specified, functions return 0 on success and -1 on error.
13
14 #include "webrtc/modules/audio_processing/utility/ring_buffer.h"
15
16 #include <stddef.h> // size_t
17 #include <stdlib.h>
18 #include <string.h>
19
20 enum Wrap {
21 SAME_WRAP,
22 DIFF_WRAP
23 };
24
25 struct RingBuffer {
26 size_t read_pos;
27 size_t write_pos;
28 size_t element_count;
29 size_t element_size;
30 enum Wrap rw_wrap;
31 char* data;
32 };
33
34 // Get address of region(s) from which we can read data.
35 // If the region is contiguous, |data_ptr_bytes_2| will be zero.
36 // If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second
37 // region. Returns room available to be read or |element_count|, whichever is
38 // smaller.
39 static size_t GetBufferReadRegions(RingBuffer* buf,
40 size_t element_count,
41 void** data_ptr_1,
42 size_t* data_ptr_bytes_1,
43 void** data_ptr_2,
44 size_t* data_ptr_bytes_2) {
45 const size_t readable_elements = WebRtc_available_read(buf);
46 const size_t read_elements = (readable_elements < element_count ?
47 readable_elements : element_count);
48 const size_t margin = buf->element_count - buf->read_pos;
49
50 // Check to see if read is not contiguous.
51 if (read_elements > margin) {
52 // Write data in two blocks that wrap the buffer.
53 *data_ptr_1 = buf->data + buf->read_pos * buf->element_size;
54 *data_ptr_bytes_1 = margin * buf->element_size;
55 *data_ptr_2 = buf->data;
56 *data_ptr_bytes_2 = (read_elements - margin) * buf->element_size;
57 } else {
58 *data_ptr_1 = buf->data + buf->read_pos * buf->element_size;
59 *data_ptr_bytes_1 = read_elements * buf->element_size;
60 *data_ptr_2 = NULL;
61 *data_ptr_bytes_2 = 0;
62 }
63
64 return read_elements;
65 }
66
67 RingBuffer* WebRtc_CreateBuffer(size_t element_count, size_t element_size) {
68 RingBuffer* self = NULL;
69 if (element_count == 0 || element_size == 0) {
70 return NULL;
71 }
72
73 self = static_cast<RingBuffer*>(malloc(sizeof(RingBuffer)));
74 if (!self) {
75 return NULL;
76 }
77
78 self->data = static_cast<char*>(malloc(element_count * element_size));
79 if (!self->data) {
80 free(self);
81 self = NULL;
82 return NULL;
83 }
84
85 self->element_count = element_count;
86 self->element_size = element_size;
87 WebRtc_InitBuffer(self);
88
89 return self;
90 }
91
92 void WebRtc_InitBuffer(RingBuffer* self) {
93 self->read_pos = 0;
94 self->write_pos = 0;
95 self->rw_wrap = SAME_WRAP;
96
97 // Initialize buffer to zeros
98 memset(self->data, 0, self->element_count * self->element_size);
99 }
100
101 void WebRtc_FreeBuffer(void* handle) {
102 RingBuffer* self = static_cast<RingBuffer*>(handle);
103 if (!self) {
104 return;
105 }
106
107 free(self->data);
108 free(self);
109 }
110
111 size_t WebRtc_ReadBuffer(RingBuffer* self,
112 void** data_ptr,
113 void* data,
114 size_t element_count) {
115 if (self == NULL) {
116 return 0;
117 }
118 if (data == NULL) {
119 return 0;
120 }
121
122 {
123 void* buf_ptr_1 = NULL;
124 void* buf_ptr_2 = NULL;
125 size_t buf_ptr_bytes_1 = 0;
126 size_t buf_ptr_bytes_2 = 0;
127 const size_t read_count = GetBufferReadRegions(self,
128 element_count,
129 &buf_ptr_1,
130 &buf_ptr_bytes_1,
131 &buf_ptr_2,
132 &buf_ptr_bytes_2);
133
134 if (buf_ptr_bytes_2 > 0) {
135 // We have a wrap around when reading the buffer. Copy the buffer data to
136 // |data| and point to it.
137 memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
138 memcpy(static_cast<char*>(data) + buf_ptr_bytes_1, buf_ptr_2,
139 buf_ptr_bytes_2);
140 buf_ptr_1 = data;
141 } else if (!data_ptr) {
142 // No wrap, but a memcpy was requested.
143 memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
144 }
145 if (data_ptr) {
146 // |buf_ptr_1| == |data| in the case of a wrap.
147 *data_ptr = buf_ptr_1;
148 }
149
150 // Update read position
151 WebRtc_MoveReadPtr(self, static_cast<int>(read_count));
152
153 return read_count;
154 }
155 }
156
157 size_t WebRtc_WriteBuffer(RingBuffer* self,
158 const void* data,
159 size_t element_count) {
160 if (!self) {
161 return 0;
162 }
163 if (!data) {
164 return 0;
165 }
166
167 {
168 const size_t free_elements = WebRtc_available_write(self);
169 const size_t write_elements = (free_elements < element_count ? free_elements
170 : element_count);
171 size_t n = write_elements;
172 const size_t margin = self->element_count - self->write_pos;
173
174 if (write_elements > margin) {
175 // Buffer wrap around when writing.
176 memcpy(self->data + self->write_pos * self->element_size,
177 data, margin * self->element_size);
178 self->write_pos = 0;
179 n -= margin;
180 self->rw_wrap = DIFF_WRAP;
181 }
182 memcpy(self->data + self->write_pos * self->element_size,
183 ((const char*) data) + ((write_elements - n) * self->element_size),
184 n * self->element_size);
185 self->write_pos += n;
186
187 return write_elements;
188 }
189 }
190
191 int WebRtc_MoveReadPtr(RingBuffer* self, int element_count) {
192 if (!self) {
193 return 0;
194 }
195
196 {
197 // We need to be able to take care of negative changes, hence use "int"
198 // instead of "size_t".
199 const int free_elements = static_cast<int>(WebRtc_available_write(self));
200 const int readable_elements = static_cast<int>(WebRtc_available_read(self));
201 int read_pos = static_cast<int>(self->read_pos);
202
203 if (element_count > readable_elements) {
204 element_count = readable_elements;
205 }
206 if (element_count < -free_elements) {
207 element_count = -free_elements;
208 }
209
210 read_pos += element_count;
211 if (read_pos > static_cast<int>(self->element_count)) {
212 // Buffer wrap around. Restart read position and wrap indicator.
213 read_pos -= static_cast<int>(self->element_count);
214 self->rw_wrap = SAME_WRAP;
215 }
216 if (read_pos < 0) {
217 // Buffer wrap around. Restart read position and wrap indicator.
218 read_pos += static_cast<int>(self->element_count);
219 self->rw_wrap = DIFF_WRAP;
220 }
221
222 self->read_pos = static_cast<size_t>(read_pos);
223
224 return element_count;
225 }
226 }
227
228 size_t WebRtc_available_read(const RingBuffer* self) {
229 if (!self) {
230 return 0;
231 }
232
233 if (self->rw_wrap == SAME_WRAP) {
234 return self->write_pos - self->read_pos;
235 } else {
236 return self->element_count - self->read_pos + self->write_pos;
237 }
238 }
239
240 size_t WebRtc_available_write(const RingBuffer* self) {
241 if (!self) {
242 return 0;
243 }
244
245 return self->element_count - WebRtc_available_read(self);
246 }
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/utility/ring_buffer.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698