MythTV master
ringbuffer.cpp
Go to the documentation of this file.
1/*
2 * ringbuffer.c
3 *
4 *
5 * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de>
6 * Metzler Brothers Systementwicklung GbR
7 * Changes to use MythTV logging
8 * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * General Public License for more details.
20 *
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
26 *
27 */
28
29#include <cstdlib>
30#include <cstring>
31#include "ringbuffer.h"
32#include "pes.h"
33
35
36#define DEBUG true
37
38int ring_init (ringbuffer *rbuf, int size)
39{
40 if (size > 0){
41 rbuf->size = size;
42 rbuf->buffer = (uint8_t *) malloc(sizeof(uint8_t)*size);
43 if (rbuf->buffer == nullptr)
44 {
45 LOG(VB_GENERAL, LOG_ERR,
46 "Not enough memory for ringbuffer");
47 return -1;
48 }
49 } else {
50 LOG(VB_GENERAL, LOG_ERR, "Wrong size for ringbuffer");
51 return -1;
52 }
53 rbuf->read_pos = 0;
54 rbuf->write_pos = 0;
55 return 0;
56}
57
58int ring_reinit (ringbuffer *rbuf, int size)
59{
60 if (size > (int)(rbuf->size)) {
61 auto *tmpalloc = (uint8_t *) realloc(rbuf->buffer,
62 sizeof(uint8_t)*size);
63 if (! tmpalloc)
64 return -1;
65 rbuf->buffer = tmpalloc;
66 if (rbuf->write_pos < rbuf->read_pos)
67 {
68 unsigned int delta = size - rbuf->size;
69 memmove(rbuf->buffer + rbuf->read_pos + delta,
70 rbuf->buffer + rbuf->read_pos,
71 rbuf->size - rbuf->read_pos);
72 rbuf->read_pos += delta;
73 }
74 rbuf->size = size;
75 }
76 return 0;
77}
79{
80 rbuf->read_pos = 0;
81 rbuf->write_pos = 0;
82}
83
84
85
87{
88 free(rbuf->buffer);
89}
90
91
92int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
93{
94 if (count <=0 ) return 0;
95 int pos = rbuf->write_pos;
96 int rest = rbuf->size - pos;
97 int free = ring_free(rbuf);
98
99 if ( free < count ){
100 if (DEBUG) {
101 LOG(VB_GENERAL, LOG_ERR,
102 QString("ringbuffer overflow %1<%2 %3")
103 .arg(free).arg(count).arg(rbuf->size));
104 }
105 return FULL_BUFFER;
106 }
107
108 if (count >= rest){
109 memcpy (rbuf->buffer+pos, data, rest);
110 if (count - rest)
111 memcpy (rbuf->buffer, data+rest, count - rest);
112 rbuf->write_pos = count - rest;
113 } else {
114 memcpy (rbuf->buffer+pos, data, count);
115 rbuf->write_pos += count;
116 }
117
118 if (DEBUG>1)
119 LOG(VB_GENERAL, LOG_ERR, QString("Buffer empty %1%%")
120 .arg(ring_free(rbuf)*100.0/rbuf->size, 0,'f',2,QChar('0')));
121 return count;
122}
123
124int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
125{
126 if (off+count > rbuf->size || off+count >ring_avail(rbuf))
127 return -1;
128 unsigned int pos = (rbuf->read_pos+off)%rbuf->size;
129 unsigned int rest = rbuf->size - pos ;
130 unsigned int avail = ring_avail(rbuf);
131
132 if ( avail < count ){
133#if 0
134 if (DEBUG)
135 LOG(VB_GENERAL, LOG_ERR,
136 QString("ringbuffer peek underflow %1<%2 %3 %4")
137 .arg(avail).arg(count).arg(pos).arg(rbuf->write_pos));
138#endif
139 return EMPTY_BUFFER;
140 }
141
142 if ( count < rest ){
143 memcpy(data, rbuf->buffer+pos, count);
144 } else {
145 memcpy(data, rbuf->buffer+pos, rest);
146 if ( count - rest)
147 memcpy(data+rest, rbuf->buffer, count - rest);
148 }
149
150 return count;
151}
152
153int ring_peek(ringbuffer *rbuf, peek_poke_vec& data, unsigned int count, uint32_t off)
154{
155 return ring_peek(rbuf, data.data(), count, off);
156}
157
158int ring_peek(ringbuffer *rbuf, peek_poke_vec& data, uint32_t off)
159{
160 return ring_peek(rbuf, data.data(), data.size(), off);
161}
162
163int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
164{
165 if (off+count > rbuf->size || off+count >ring_avail(rbuf))
166 return -1;
167 unsigned int pos = (rbuf->read_pos+off)%rbuf->size;
168 unsigned int rest = rbuf->size - pos ;
169 unsigned int avail = ring_avail(rbuf);
170
171 if ( avail < count ){
172#if 0
173 if (DEBUG)
174 LOG(VB_GENERAL, LOG_ERR,
175 QString("ringbuffer peek underflow %1<%2 %3 %4")
176 .arg(avail).arg(count).arg(pos).arg(rbuf->write_pos));
177#endif
178 return EMPTY_BUFFER;
179 }
180
181 if ( count < rest ){
182 memcpy(rbuf->buffer+pos, data, count);
183 } else {
184 memcpy(rbuf->buffer+pos, data, rest);
185 if ( count - rest)
186 memcpy(rbuf->buffer, data+rest, count - rest);
187 }
188
189 return count;
190}
191
192int ring_poke(ringbuffer *rbuf, peek_poke_vec& data, unsigned int count, uint32_t off)
193{
194 return ring_poke(rbuf, data.data(), count, off);
195}
196
197int ring_poke(ringbuffer *rbuf, peek_poke_vec& data, uint32_t off)
198{
199 return ring_poke(rbuf, data.data(), data.size(), off);
200}
201
202int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
203{
204 if (count <=0 ) return 0;
205 int pos = rbuf->read_pos;
206 int rest = rbuf->size - pos;
207 int avail = ring_avail(rbuf);
208
209 if ( avail < count ){
210#if 0
211 if (DEBUG)
212 LOG(VB_GENERAL, LOG_ERR,
213 QString("ringbuffer underflow %1<%2 %3 \n")
214 .arg(avail).arg(count).arg(rbuf->size));
215#endif
216 return EMPTY_BUFFER;
217 }
218
219 if ( count < rest ){
220 memcpy(data, rbuf->buffer+pos, count);
221 rbuf->read_pos += count;
222 } else {
223 memcpy(data, rbuf->buffer+pos, rest);
224 if ( count - rest)
225 memcpy(data+rest, rbuf->buffer, count - rest);
226 rbuf->read_pos = count - rest;
227 }
228
229 if (DEBUG>1)
230 LOG(VB_GENERAL, LOG_ERR, QString("Buffer empty %1%%")
231 .arg(ring_free(rbuf)*100.0/rbuf->size, 0,'f',2,QChar('0')));
232 return count;
233}
234
235int ring_skip(ringbuffer *rbuf, int count)
236{
237 if (count <=0 ) return -1;
238 int pos = rbuf->read_pos;
239 int rest = rbuf->size - pos;
240 int avail = ring_avail(rbuf);
241
242 if ( avail < count ){
243#if 0
244 LOG(VB_GENERAL, LOG_ERR,
245 QString("ringbuffer skip underflow %1<%2 %3 %4\n")
246 .arg(avail).arg(count).arg(pos).arg(rbuf->write_pos));
247#endif
248 return EMPTY_BUFFER;
249 }
250 if ( count < rest ){
251 rbuf->read_pos += count;
252 } else {
253 rbuf->read_pos = count - rest;
254 }
255
256 if (DEBUG>1)
257 LOG(VB_GENERAL, LOG_ERR, QString("Buffer empty %1%%")
258 .arg(ring_free(rbuf)*100.0/rbuf->size, 0,'f',2,QChar('0')));
259 return count;
260}
261
262
263
264int ring_write_file(ringbuffer *rbuf, int fd, int count)
265{
266 int rr = 0;
267
268 if (count <=0 ) return 0;
269 int pos = rbuf->write_pos;
270 int rest = rbuf->size - pos;
271 int free = ring_free(rbuf);
272
273 if ( free < count ){
274 if (DEBUG) {
275 LOG(VB_GENERAL, LOG_ERR,
276 QString("ringbuffer overflow %1<%2 %3 %4\n")
277 .arg(free).arg(count).arg(pos).arg(rbuf->read_pos));
278 }
279 return FULL_BUFFER;
280 }
281
282 if (count >= rest){
283 rr = read (fd, rbuf->buffer+pos, rest);
284 if (rr == rest && count - rest)
285 rr += read (fd, rbuf->buffer, count - rest);
286 if (rr >=0)
287 rbuf->write_pos = (pos + rr) % rbuf->size;
288 } else {
289 rr = read (fd, rbuf->buffer+pos, count);
290 if (rr >=0)
291 rbuf->write_pos += rr;
292 }
293
294 if (DEBUG>1)
295 LOG(VB_GENERAL, LOG_ERR, QString("Buffer empty %.2f%%")
296 .arg(ring_free(rbuf)*100.0/rbuf->size, 0,'f',2,QChar('0')));
297 return rr;
298}
299
300
301
302int ring_read_file(ringbuffer *rbuf, int fd, int count)
303{
304 int rr = 0;
305
306 if (count <=0 ) return -1;
307 int pos = rbuf->read_pos;
308 int rest = rbuf->size - pos;
309 int avail = ring_avail(rbuf);
310
311 if ( avail < count ){
312#if 0
313 if (DEBUG)
314 LOG(VB_GENERAL, LOG_ERR,
315 QString("ringbuffer underflow %1<%2 %3 %4")
316 .arg(avail).arg(count).arg(pos).arg(rbuf->write_pos));
317#endif
318 return EMPTY_BUFFER;
319 }
320
321 if (count >= rest){
322 rr = write (fd, rbuf->buffer+pos, rest);
323 if (rr == rest && count - rest)
324 rr += write (fd, rbuf->buffer, count - rest);
325 if (rr >=0)
326 rbuf->read_pos = (pos + rr) % rbuf->size;
327 } else {
328 rr = write (fd, rbuf->buffer+pos, count);
329 if (rr >=0)
330 rbuf->read_pos += rr;
331 }
332
333
334 if (DEBUG>1)
335 LOG(VB_GENERAL, LOG_ERR, QString("Buffer empty %1%%")
336 .arg(ring_free(rbuf)*100.0/rbuf->size, 0,'f',2,QChar('0')));
337 return rr;
338}
339
340
341static void show(uint8_t *buf, int length)
342{
343 QString buffer;
344
345 for (int i=0; i<length; i+=16){
346 int j = 0;
347 for (j=0; j < 8 && j+i<length; j++)
348 buffer += QString("0x%1 ").arg(buf[i+j],16,2,QChar('0'));
349 for (int r=j; r<8; r++)
350 buffer += " ";
351
352 buffer += " ";
353
354 for (j=8; j < 16 && j+i<length; j++)
355 buffer += QString("0x%1 ").arg(buf[i+j],16,2,QChar('0'));
356 for (int r=j; r<16; r++)
357 buffer += " ";
358
359 for (j=0; j < 16 && j+i<length; j++){
360 switch(buf[i+j]){
361 case '0'...'Z':
362 case 'a'...'z':
363 buffer += QString(QChar(buf[i+j]));
364 break;
365 default:
366 buffer += ".";
367 }
368 }
369 LOG(VB_GENERAL, LOG_INFO, buffer);
370 }
371}
372
373void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off)
374{
375 if (off+count > rbuf->size || off+count >ring_avail(rbuf))
376 return;
377 unsigned int pos = (rbuf->read_pos+off)%rbuf->size;
378 unsigned int rest = rbuf->size - pos ;
379 unsigned int avail = ring_avail(rbuf);
380
381 if ( avail < count ){
382#if 0
383 if (DEBUG)
384 LOG(VB_GENERAL, LOG_ERR,
385 QString("ringbuffer peek underflow %1<%2 %3 %4\n")
386 .arg(avail).arg(count).arg(pos).arg(rbuf->write_pos));
387#endif
388 return;
389 }
390
391 if ( count < rest ){
392 show(rbuf->buffer+pos, count);
393 } else {
394 show(rbuf->buffer+pos, rest);
395 if ( count - rest)
396 show(rbuf->buffer, count - rest);
397 }
398}
399
400
401int dummy_init(dummy_buffer *dbuf, int s)
402{
403 dbuf->size = s;
404 dbuf->fill = 0;
405 if (ring_init(&dbuf->time_index, DBUF_INDEX*sizeof(uint64_t)) < 0)
406 return -1;
407 if (ring_init(&dbuf->data_index, DBUF_INDEX*sizeof(int32_t)) < 0)
408 return -1;
409
410 return 0;
411}
412
414{
415 ring_destroy(&dbuf->time_index);
416 ring_destroy(&dbuf->data_index);
417}
418
420{
421 dbuf->fill = 0;
422 ring_clear(&dbuf->time_index);
423 ring_clear(&dbuf->data_index);
424}
425
426int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size)
427{
428 if (dummy_space(dbuf) < size) return -1;
429#if 0
430 LOG(VB_GENERAL, LOG_INFO, QString("add %1 ").arg(dummy_space(dbuf)));
431#endif
432 dbuf->fill += size;
433 if (ring_write(&dbuf->time_index, (uint8_t *)&time, sizeof(uint64_t)) < 0)
434 return -2;
435 if (ring_write(&dbuf->data_index, (uint8_t *)&size, sizeof(uint32_t)) < 0)
436 return -3;
437#if 0
438 LOG(VB_GENERAL, LOG_INFO,
439 QString(" - %1 = %2").arg(size).arg(dummy_space(dbuf)));
440#endif
441 return size;
442}
443
444int dummy_delete(dummy_buffer *dbuf, uint64_t time)
445{
446 uint64_t rtime = 0;
447 uint32_t size = 0;
448 int ex=0;
449 uint32_t dsize=0;
450
451 while (ex == 0)
452 {
453 if (ring_peek(&dbuf->time_index,(uint8_t *) &rtime,
454 sizeof(uint64_t), 0)<0){
455 if (dsize) break;
456 return -1;
457 }
458 if (ptscmp(rtime,time) < 0){
459 ring_read(&dbuf->time_index,(uint8_t *) &rtime,
460 sizeof(uint64_t));
461 ring_read(&dbuf->data_index,(uint8_t *) &size,
462 sizeof(uint32_t));
463 dsize += size;
464 } else {
465 ex = 1;
466 }
467 }
468#if 0
469 LOG(VB_GENERAL, LOG_INFO, QString("delete %1 ").arg(dummy_space(dbuf)));
470#endif
471 dbuf->fill -= dsize;
472#if 0
473 LOG(VB_GENERAL, LOG_INFO,
474 QString(" + %1 = %2").arg(dsize).arg(dummy_space(dbuf)));
475#endif
476
477 return dsize;
478}
479
480#if 0
481static void dummy_print(dummy_buffer *dbuf)
482{
483 uint64_t rtime = 0;
484 uint32_t size = 0;
485 int avail = ring_avail(&dbuf->time_index) / sizeof(uint64_t);
486 for (int i = 0; i < avail; i++) {
487 ring_peek(&dbuf->time_index,(uint8_t *) &rtime,
488 sizeof(uint64_t), i * sizeof(uint64_t));
489 ring_peek(&dbuf->data_index,(uint8_t *) &size,
490 sizeof(uint32_t), i * sizeof(uint32_t));
491
492 LOG(VB_GENERAL, LOG_INFO, QString("%1 : %2 %3").arg(i)
493 .arg(rtime).arg(size));
494 }
495 LOG(VB_GENERAL, LOG_INFO, QString("Used: %d Free: %d data-free: %d")
496 .arg(avail).arg(1000-avail).arg(dbuf->size - dbuf->fill));
497}
498#endif
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
def read(device=None, features=[])
Definition: disc.py:35
def write(text, progress=True)
Definition: mythburn.py:307
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:114
int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size)
Definition: ringbuffer.cpp:426
static void show(uint8_t *buf, int length)
Definition: ringbuffer.cpp:341
void dummy_destroy(dummy_buffer *dbuf)
Definition: ringbuffer.cpp:413
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:202
void ring_destroy(ringbuffer *rbuf)
Definition: ringbuffer.cpp:86
int ring_reinit(ringbuffer *rbuf, int size)
Definition: ringbuffer.cpp:58
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:92
int ring_read_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.cpp:302
int dummy_init(dummy_buffer *dbuf, int s)
Definition: ringbuffer.cpp:401
void ring_clear(ringbuffer *rbuf)
Definition: ringbuffer.cpp:78
void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off)
Definition: ringbuffer.cpp:373
int dummy_delete(dummy_buffer *dbuf, uint64_t time)
Definition: ringbuffer.cpp:444
int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.cpp:124
int ring_write_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.cpp:264
int ring_skip(ringbuffer *rbuf, int count)
Definition: ringbuffer.cpp:235
void dummy_clear(dummy_buffer *dbuf)
Definition: ringbuffer.cpp:419
#define DEBUG
Definition: ringbuffer.cpp:36
int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.cpp:163
int ring_init(ringbuffer *rbuf, int size)
Definition: ringbuffer.cpp:38
static unsigned int ring_avail(ringbuffer *rbuf)
Definition: ringbuffer.h:108
#define EMPTY_BUFFER
Definition: ringbuffer.h:38
static unsigned int ring_free(ringbuffer *rbuf)
Definition: ringbuffer.h:101
#define DBUF_INDEX
Definition: ringbuffer.h:47
std::vector< uint8_t > peek_poke_vec
Definition: ringbuffer.h:35
static uint32_t dummy_space(dummy_buffer *dbuf)
Definition: ringbuffer.h:117
#define FULL_BUFFER
Definition: ringbuffer.h:37
ringbuffer data_index
Definition: ringbuffer.h:53
ringbuffer time_index
Definition: ringbuffer.h:52
uint32_t size
Definition: ringbuffer.h:50
uint32_t fill
Definition: ringbuffer.h:51
int read_pos
Definition: ringbuffer.h:40
int write_pos
Definition: ringbuffer.h:41
uint8_t * buffer
Definition: ringbuffer.h:43
uint32_t size
Definition: ringbuffer.h:42