MythTV  master
ringbuffer.c
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 <stdlib.h>
30 #include <string.h>
31 #include "ringbuffer.h"
32 #include "pes.h"
33 
34 #include "mythlogging.h"
35 
36 #define DEBUG 1
37 int ring_init (ringbuffer *rbuf, int size)
38 {
39  if (size > 0){
40  rbuf->size = size;
41  if( !(rbuf->buffer = (uint8_t *) malloc(sizeof(uint8_t)*size)) ){
42  LOG(VB_GENERAL, LOG_ERR,
43  "Not enough memory for ringbuffer");
44  return -1;
45  }
46  } else {
47  LOG(VB_GENERAL, LOG_ERR, "Wrong size for ringbuffer");
48  return -1;
49  }
50  rbuf->read_pos = 0;
51  rbuf->write_pos = 0;
52  return 0;
53 }
54 
55 int ring_reinit (ringbuffer *rbuf, int size)
56 {
57  if (size > (int)(rbuf->size)) {
58  uint8_t *tmpalloc = (uint8_t *) realloc(rbuf->buffer,
59  sizeof(uint8_t)*size);
60  if (! tmpalloc)
61  return -1;
62  rbuf->buffer = tmpalloc;
63  if (rbuf->write_pos < rbuf->read_pos)
64  {
65  unsigned int delta = size - rbuf->size;
66  memmove(rbuf->buffer + rbuf->read_pos + delta,
67  rbuf->buffer + rbuf->read_pos,
68  rbuf->size - rbuf->read_pos);
69  rbuf->read_pos += delta;
70  }
71  rbuf->size = size;
72  }
73  return 0;
74 }
76 {
77  rbuf->read_pos = 0;
78  rbuf->write_pos = 0;
79 }
80 
81 
82 
84 {
85  free(rbuf->buffer);
86 }
87 
88 
89 int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
90 {
91  if (count <=0 ) return 0;
92  int pos = rbuf->write_pos;
93  int rest = rbuf->size - pos;
94  int free = ring_free(rbuf);
95 
96  if ( free < count ){
97  if (DEBUG) {
98  LOG(VB_GENERAL, LOG_ERR,
99  "ringbuffer overflow %d<%d %d",
100  free, count, rbuf->size);
101  }
102  return FULL_BUFFER;
103  }
104 
105  if (count >= rest){
106  memcpy (rbuf->buffer+pos, data, rest);
107  if (count - rest)
108  memcpy (rbuf->buffer, data+rest, count - rest);
109  rbuf->write_pos = count - rest;
110  } else {
111  memcpy (rbuf->buffer+pos, data, count);
112  rbuf->write_pos += count;
113  }
114 
115  if (DEBUG>1)
116  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
117  ring_free(rbuf)*100.0/rbuf->size);
118  return count;
119 }
120 
121 int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
122 {
123  if (off+count > rbuf->size || off+count >ring_avail(rbuf))
124  return -1;
125  unsigned int pos = (rbuf->read_pos+off)%rbuf->size;
126  unsigned int rest = rbuf->size - pos ;
127  unsigned int avail = ring_avail(rbuf);
128 
129  if ( avail < count ){
130 #if 0
131  if (DEBUG)
132  LOG(VB_GENERAL, LOG_ERR,
133  "ringbuffer peek underflow %d<%d %d %d",
134  avail, count, pos, rbuf->write_pos);
135 #endif
136  return EMPTY_BUFFER;
137  }
138 
139  if ( count < rest ){
140  memcpy(data, rbuf->buffer+pos, count);
141  } else {
142  memcpy(data, rbuf->buffer+pos, rest);
143  if ( count - rest)
144  memcpy(data+rest, rbuf->buffer, count - rest);
145  }
146 
147  return count;
148 }
149 
150 int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
151 {
152  if (off+count > rbuf->size || off+count >ring_avail(rbuf))
153  return -1;
154  unsigned int pos = (rbuf->read_pos+off)%rbuf->size;
155  unsigned int rest = rbuf->size - pos ;
156  unsigned int avail = ring_avail(rbuf);
157 
158  if ( avail < count ){
159 #if 0
160  if (DEBUG)
161  LOG(VB_GENERAL, LOG_ERR,
162  "ringbuffer peek underflow %d<%d %d %d",
163  avail, count, pos, rbuf->write_pos);
164 #endif
165  return EMPTY_BUFFER;
166  }
167 
168  if ( count < rest ){
169  memcpy(rbuf->buffer+pos, data, count);
170  } else {
171  memcpy(rbuf->buffer+pos, data, rest);
172  if ( count - rest)
173  memcpy(rbuf->buffer, data+rest, count - rest);
174  }
175 
176  return count;
177 }
178 
179 int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
180 {
181  if (count <=0 ) return 0;
182  int pos = rbuf->read_pos;
183  int rest = rbuf->size - pos;
184  int avail = ring_avail(rbuf);
185 
186  if ( avail < count ){
187 #if 0
188  if (DEBUG)
189  LOG(VB_GENERAL, LOG_ERR,
190  "ringbuffer underflow %d<%d %d \n",
191  avail, count, rbuf->size);
192 #endif
193  return EMPTY_BUFFER;
194  }
195 
196  if ( count < rest ){
197  memcpy(data, rbuf->buffer+pos, count);
198  rbuf->read_pos += count;
199  } else {
200  memcpy(data, rbuf->buffer+pos, rest);
201  if ( count - rest)
202  memcpy(data+rest, rbuf->buffer, count - rest);
203  rbuf->read_pos = count - rest;
204  }
205 
206  if (DEBUG>1)
207  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
208  ring_free(rbuf)*100.0/rbuf->size);
209  return count;
210 }
211 
212 int ring_skip(ringbuffer *rbuf, int count)
213 {
214  if (count <=0 ) return -1;
215  int pos = rbuf->read_pos;
216  int rest = rbuf->size - pos;
217  int avail = ring_avail(rbuf);
218 
219  if ( avail < count ){
220 #if 0
221  LOG(VB_GENERAL, LOG_ERR,
222  "ringbuffer skip underflow %d<%d %d %d\n",
223  avail, count, pos, rbuf->write_pos);
224 #endif
225  return EMPTY_BUFFER;
226  }
227  if ( count < rest ){
228  rbuf->read_pos += count;
229  } else {
230  rbuf->read_pos = count - rest;
231  }
232 
233  if (DEBUG>1)
234  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
235  ring_free(rbuf)*100.0/rbuf->size);
236  return count;
237 }
238 
239 
240 
241 int ring_write_file(ringbuffer *rbuf, int fd, int count)
242 {
243  int rr = 0;
244 
245  if (count <=0 ) return 0;
246  int pos = rbuf->write_pos;
247  int rest = rbuf->size - pos;
248  int free = ring_free(rbuf);
249 
250  if ( free < count ){
251  if (DEBUG) {
252  LOG(VB_GENERAL, LOG_ERR,
253  "ringbuffer overflow %d<%d %d %d\n",
254  free, count, pos, rbuf->read_pos);
255  }
256  return FULL_BUFFER;
257  }
258 
259  if (count >= rest){
260  rr = read (fd, rbuf->buffer+pos, rest);
261  if (rr == rest && count - rest)
262  rr += read (fd, rbuf->buffer, count - rest);
263  if (rr >=0)
264  rbuf->write_pos = (pos + rr) % rbuf->size;
265  } else {
266  rr = read (fd, rbuf->buffer+pos, count);
267  if (rr >=0)
268  rbuf->write_pos += rr;
269  }
270 
271  if (DEBUG>1)
272  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
273  ring_free(rbuf)*100.0/rbuf->size);
274  return rr;
275 }
276 
277 
278 
279 int ring_read_file(ringbuffer *rbuf, int fd, int count)
280 {
281  int rr = 0;
282 
283  if (count <=0 ) return -1;
284  int pos = rbuf->read_pos;
285  int rest = rbuf->size - pos;
286  int avail = ring_avail(rbuf);
287 
288  if ( avail < count ){
289 #if 0
290  if (DEBUG)
291  LOG(VB_GENERAL, LOG_ERR,
292  "ringbuffer underflow %d<%d %d %d",
293  avail, count, pos, rbuf->write_pos);
294 #endif
295  return EMPTY_BUFFER;
296  }
297 
298  if (count >= rest){
299  rr = write (fd, rbuf->buffer+pos, rest);
300  if (rr == rest && count - rest)
301  rr += write (fd, rbuf->buffer, count - rest);
302  if (rr >=0)
303  rbuf->read_pos = (pos + rr) % rbuf->size;
304  } else {
305  rr = write (fd, rbuf->buffer+pos, count);
306  if (rr >=0)
307  rbuf->read_pos += rr;
308  }
309 
310 
311  if (DEBUG>1)
312  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
313  ring_free(rbuf)*100.0/rbuf->size);
314  return rr;
315 }
316 
317 
318 static void show(uint8_t *buf, int length)
319 {
320  uint8_t temp[8];
321  uint8_t buffer[100];
322  buffer[0] = '\0';
323 
324  for (int i=0; i<length; i+=16){
325  int j = 0;
326  for (j=0; j < 8 && j+i<length; j++)
327  {
328  sprintf(temp, "0x%02x ", (int)(buf[i+j]));
329  strcat(buffer, temp);
330  }
331  for (int r=j; r<8; r++)
332  strcat(buffer, " ");
333 
334  strcat(buffer," ");
335 
336  for (j=8; j < 16 && j+i<length; j++)
337  {
338  sprintf(temp, "0x%02x ", (int)(buf[i+j]));
339  strcat(buffer, temp);
340  }
341  for (int r=j; r<16; r++)
342  strcat(buffer, " ");
343 
344  for (j=0; j < 16 && j+i<length; j++){
345  switch(buf[i+j]){
346  case '0'...'Z':
347  case 'a'...'z':
348  sprintf(temp, "%c", buf[i+j]);
349  break;
350  default:
351  sprintf(temp, ".");
352  }
353  strcat(buffer, temp);
354  }
355  LOG(VB_GENERAL, LOG_INFO, buffer);
356  }
357 }
358 
359 void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off)
360 {
361  if (off+count > rbuf->size || off+count >ring_avail(rbuf))
362  return;
363  unsigned int pos = (rbuf->read_pos+off)%rbuf->size;
364  unsigned int rest = rbuf->size - pos ;
365  unsigned int avail = ring_avail(rbuf);
366 
367  if ( avail < count ){
368 #if 0
369  if (DEBUG)
370  LOG(VB_GENERAL, LOG_ERR,
371  "ringbuffer peek underflow %d<%d %d %d\n",
372  avail, count, pos, rbuf->write_pos);
373 #endif
374  return;
375  }
376 
377  if ( count < rest ){
378  show(rbuf->buffer+pos, count);
379  } else {
380  show(rbuf->buffer+pos, rest);
381  if ( count - rest)
382  show(rbuf->buffer, count - rest);
383  }
384 }
385 
386 
387 int dummy_init(dummy_buffer *dbuf, int s)
388 {
389  dbuf->size = s;
390  dbuf->fill = 0;
391  if (ring_init(&dbuf->time_index, DBUF_INDEX*sizeof(uint64_t)) < 0)
392  return -1;
393  if (ring_init(&dbuf->data_index, DBUF_INDEX*sizeof(int32_t)) < 0)
394  return -1;
395 
396  return 0;
397 }
398 
400 {
401  ring_destroy(&dbuf->time_index);
402  ring_destroy(&dbuf->data_index);
403 }
404 
406 {
407  dbuf->fill = 0;
408  ring_clear(&dbuf->time_index);
409  ring_clear(&dbuf->data_index);
410 }
411 
412 int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size)
413 {
414  if (dummy_space(dbuf) < size) return -1;
415 #if 0
416  LOG(VB_GENERAL, LOG_INFO, "add %d ", dummy_space(dbuf));
417 #endif
418  dbuf->fill += size;
419  if (ring_write(&dbuf->time_index, (uint8_t *)&time, sizeof(uint64_t)) < 0)
420  return -2;
421  if (ring_write(&dbuf->data_index, (uint8_t *)&size, sizeof(uint32_t)) < 0)
422  return -3;
423 #if 0
424  LOG(VB_GENERAL, LOG_INFO, " - %d = %d", size, dummy_space(dbuf));
425 #endif
426  return size;
427 }
428 
429 int dummy_delete(dummy_buffer *dbuf, uint64_t time)
430 {
431  uint64_t rtime = 0;
432  uint32_t size = 0;
433  int ex=0;
434  uint32_t dsize=0;
435 
436  do {
437  if (ring_peek(&dbuf->time_index,(uint8_t *) &rtime,
438  sizeof(uint64_t), 0)<0){
439  if (dsize) break;
440  return -1;
441  }
442  if (ptscmp(rtime,time) < 0){
443  ring_read(&dbuf->time_index,(uint8_t *) &rtime,
444  sizeof(uint64_t));
445  ring_read(&dbuf->data_index,(uint8_t *) &size,
446  sizeof(uint32_t));
447  dsize += size;
448  } else ex = 1;
449  } while (!ex);
450 #if 0
451  LOG(VB_GENERAL, LOG_INFO, "delete %d ", dummy_space(dbuf));
452 #endif
453  dbuf->fill -= dsize;
454 #if 0
455  LOG(VB_GENERAL, LOG_INFO, " + %d = %d", dsize, dummy_space(dbuf));
456 #endif
457 
458  return dsize;
459 }
460 
461 static void dummy_print(dummy_buffer *dbuf)
462 {
463  uint64_t rtime = 0;
464  uint32_t size = 0;
465  int avail = ring_avail(&dbuf->time_index) / sizeof(uint64_t);
466  for (int i = 0; i < avail; i++) {
467  ring_peek(&dbuf->time_index,(uint8_t *) &rtime,
468  sizeof(uint64_t), i * sizeof(uint64_t));
469  ring_peek(&dbuf->data_index,(uint8_t *) &size,
470  sizeof(uint32_t), i * sizeof(uint32_t));
471 
472  LOG(VB_GENERAL, LOG_INFO, "%d : %llu %u", i,
473  (long long unsigned int)rtime, size);
474  }
475  LOG(VB_GENERAL, LOG_INFO, "Used: %d Free: %d data-free: %d", avail,
476  1000-avail, dbuf->size - dbuf->fill);
477 }
def write(text, progress=True)
Definition: mythburn.py:279
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.c:89
void ring_destroy(ringbuffer *rbuf)
Definition: ringbuffer.c:83
int ring_write_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.c:241
int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size)
Definition: ringbuffer.c:412
void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off)
Definition: ringbuffer.c:359
def read(device=None, features=[])
Definition: disc.py:35
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.c:179
#define DEBUG
Definition: ringbuffer.c:36
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.c:114
static void show(uint8_t *buf, int length)
Definition: ringbuffer.c:318
void dummy_destroy(dummy_buffer *dbuf)
Definition: ringbuffer.c:399
static unsigned int ring_avail(ringbuffer *rbuf)
static void dummy_print(dummy_buffer *dbuf)
Definition: ringbuffer.c:461
void dummy_clear(dummy_buffer *dbuf)
Definition: ringbuffer.c:405
int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.c:121
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
int ring_reinit(ringbuffer *rbuf, int size)
Definition: ringbuffer.c:55
void ring_clear(ringbuffer *rbuf)
Definition: ringbuffer.c:75
int dummy_init(dummy_buffer *dbuf, int s)
Definition: ringbuffer.c:387
static uint32_t dummy_space(dummy_buffer *dbuf)
int dummy_delete(dummy_buffer *dbuf, uint64_t time)
Definition: ringbuffer.c:429
int ring_skip(ringbuffer *rbuf, int count)
Definition: ringbuffer.c:212
int ring_init(ringbuffer *rbuf, int size)
Definition: ringbuffer.c:37
int ring_read_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.c:279
int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.c:150
static unsigned int ring_free(ringbuffer *rbuf)