|
MythTV
0.26-pre
|
00001 /* 00002 * ringbuffer.c 00003 * 00004 * 00005 * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de> 00006 * Metzler Brothers Systementwicklung GbR 00007 * Changes to use MythTV logging 00008 * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org> 00009 * 00010 * This program is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU General Public License 00012 * as published by the Free Software Foundation; either version 2 00013 * of the License, or (at your option) any later version. 00014 * 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * General Public License for more details. 00020 * 00021 * 00022 * You should have received a copy of the GNU General Public License 00023 * along with this program; if not, write to the Free Software 00024 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00025 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00026 * 00027 */ 00028 00029 #include <stdlib.h> 00030 #include <string.h> 00031 #include "ringbuffer.h" 00032 #include "pes.h" 00033 00034 #include "mythlogging.h" 00035 00036 #define DEBUG 1 00037 int ring_init (ringbuffer *rbuf, int size) 00038 { 00039 if (size > 0){ 00040 rbuf->size = size; 00041 if( !(rbuf->buffer = (uint8_t *) malloc(sizeof(uint8_t)*size)) ){ 00042 LOG(VB_GENERAL, LOG_ERR, 00043 "Not enough memory for ringbuffer"); 00044 return -1; 00045 } 00046 } else { 00047 LOG(VB_GENERAL, LOG_ERR, "Wrong size for ringbuffer"); 00048 return -1; 00049 } 00050 rbuf->read_pos = 0; 00051 rbuf->write_pos = 0; 00052 return 0; 00053 } 00054 00055 int ring_reinit (ringbuffer *rbuf, int size) 00056 { 00057 if (size > (int)(rbuf->size)) { 00058 uint8_t *tmpalloc = (uint8_t *) realloc(rbuf->buffer, 00059 sizeof(uint8_t)*size); 00060 if (! tmpalloc) 00061 return -1; 00062 rbuf->buffer = tmpalloc; 00063 if (rbuf->write_pos < rbuf->read_pos) 00064 { 00065 unsigned int delta = size - rbuf->size; 00066 memmove(rbuf->buffer + rbuf->read_pos + delta, 00067 rbuf->buffer + rbuf->read_pos, 00068 rbuf->size - rbuf->read_pos); 00069 rbuf->read_pos += delta; 00070 } 00071 rbuf->size = size; 00072 } 00073 return 0; 00074 } 00075 void ring_clear(ringbuffer *rbuf) 00076 { 00077 rbuf->read_pos = 0; 00078 rbuf->write_pos = 0; 00079 } 00080 00081 00082 00083 void ring_destroy(ringbuffer *rbuf) 00084 { 00085 free(rbuf->buffer); 00086 } 00087 00088 00089 int ring_write(ringbuffer *rbuf, uint8_t *data, int count) 00090 { 00091 00092 int free, pos, rest; 00093 00094 if (count <=0 ) return 0; 00095 pos = rbuf->write_pos; 00096 rest = rbuf->size - pos; 00097 free = ring_free(rbuf); 00098 00099 if ( free < count ){ 00100 if (DEBUG) 00101 LOG(VB_GENERAL, LOG_ERR, 00102 "ringbuffer overflow %d<%d %d", 00103 free, count, rbuf->size); 00104 return FULL_BUFFER; 00105 } 00106 00107 if (count >= rest){ 00108 memcpy (rbuf->buffer+pos, data, rest); 00109 if (count - rest) 00110 memcpy (rbuf->buffer, data+rest, count - rest); 00111 rbuf->write_pos = count - rest; 00112 } else { 00113 memcpy (rbuf->buffer+pos, data, count); 00114 rbuf->write_pos += count; 00115 } 00116 00117 if (DEBUG>1) 00118 LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%", 00119 ring_free(rbuf)*100.0/rbuf->size); 00120 return count; 00121 } 00122 00123 int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off) 00124 { 00125 00126 unsigned int avail, pos, rest; 00127 00128 if (off+count > rbuf->size || off+count >ring_avail(rbuf)) 00129 return -1; 00130 pos = (rbuf->read_pos+off)%rbuf->size; 00131 rest = rbuf->size - pos ; 00132 avail = ring_avail(rbuf); 00133 00134 00135 if ( avail < count ){ 00136 #if 0 00137 if (DEBUG) 00138 LOG(VB_GENERAL, LOG_ERR, 00139 "ringbuffer peek underflow %d<%d %d %d", 00140 avail, count, pos, rbuf->write_pos); 00141 #endif 00142 return EMPTY_BUFFER; 00143 } 00144 00145 if ( count < rest ){ 00146 memcpy(data, rbuf->buffer+pos, count); 00147 } else { 00148 memcpy(data, rbuf->buffer+pos, rest); 00149 if ( count - rest) 00150 memcpy(data+rest, rbuf->buffer, count - rest); 00151 } 00152 00153 return count; 00154 } 00155 00156 int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off) 00157 { 00158 00159 unsigned int avail, pos, rest; 00160 00161 if (off+count > rbuf->size || off+count >ring_avail(rbuf)) 00162 return -1; 00163 pos = (rbuf->read_pos+off)%rbuf->size; 00164 rest = rbuf->size - pos ; 00165 avail = ring_avail(rbuf); 00166 00167 00168 if ( avail < count ){ 00169 #if 0 00170 if (DEBUG) 00171 LOG(VB_GENERAL, LOG_ERR, 00172 "ringbuffer peek underflow %d<%d %d %d", 00173 avail, count, pos, rbuf->write_pos); 00174 #endif 00175 return EMPTY_BUFFER; 00176 } 00177 00178 if ( count < rest ){ 00179 memcpy(rbuf->buffer+pos, data, count); 00180 } else { 00181 memcpy(rbuf->buffer+pos, data, rest); 00182 if ( count - rest) 00183 memcpy(rbuf->buffer, data+rest, count - rest); 00184 } 00185 00186 return count; 00187 } 00188 00189 int ring_read(ringbuffer *rbuf, uint8_t *data, int count) 00190 { 00191 00192 int avail, pos, rest; 00193 00194 if (count <=0 ) return 0; 00195 pos = rbuf->read_pos; 00196 rest = rbuf->size - pos; 00197 avail = ring_avail(rbuf); 00198 00199 if ( avail < count ){ 00200 #if 0 00201 if (DEBUG) 00202 LOG(VB_GENERAL, LOG_ERR, 00203 "ringbuffer underflow %d<%d %d \n", 00204 avail, count, rbuf->size); 00205 #endif 00206 return EMPTY_BUFFER; 00207 } 00208 00209 if ( count < rest ){ 00210 memcpy(data, rbuf->buffer+pos, count); 00211 rbuf->read_pos += count; 00212 } else { 00213 memcpy(data, rbuf->buffer+pos, rest); 00214 if ( count - rest) 00215 memcpy(data+rest, rbuf->buffer, count - rest); 00216 rbuf->read_pos = count - rest; 00217 } 00218 00219 if (DEBUG>1) 00220 LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%", 00221 ring_free(rbuf)*100.0/rbuf->size); 00222 return count; 00223 } 00224 00225 int ring_skip(ringbuffer *rbuf, int count) 00226 { 00227 00228 int avail, pos, rest; 00229 00230 if (count <=0 ) return -1; 00231 pos = rbuf->read_pos; 00232 rest = rbuf->size - pos; 00233 avail = ring_avail(rbuf); 00234 00235 if ( avail < count ){ 00236 #if 0 00237 LOG(VB_GENERAL, LOG_ERR, 00238 "ringbuffer skip underflow %d<%d %d %d\n", 00239 avail, count, pos, rbuf->write_pos); 00240 #endif 00241 return EMPTY_BUFFER; 00242 } 00243 if ( count < rest ){ 00244 rbuf->read_pos += count; 00245 } else { 00246 rbuf->read_pos = count - rest; 00247 } 00248 00249 if (DEBUG>1) 00250 LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%", 00251 ring_free(rbuf)*100.0/rbuf->size); 00252 return count; 00253 } 00254 00255 00256 00257 int ring_write_file(ringbuffer *rbuf, int fd, int count) 00258 { 00259 00260 int free, pos, rest, rr; 00261 00262 if (count <=0 ) return 0; 00263 pos = rbuf->write_pos; 00264 rest = rbuf->size - pos; 00265 free = ring_free(rbuf); 00266 00267 if ( free < count ){ 00268 if (DEBUG) 00269 LOG(VB_GENERAL, LOG_ERR, 00270 "ringbuffer overflow %d<%d %d %d\n", 00271 free, count, pos, rbuf->read_pos); 00272 return FULL_BUFFER; 00273 } 00274 00275 if (count >= rest){ 00276 rr = read (fd, rbuf->buffer+pos, rest); 00277 if (rr == rest && count - rest) 00278 rr += read (fd, rbuf->buffer, count - rest); 00279 if (rr >=0) 00280 rbuf->write_pos = (pos + rr) % rbuf->size; 00281 } else { 00282 rr = read (fd, rbuf->buffer+pos, count); 00283 if (rr >=0) 00284 rbuf->write_pos += rr; 00285 } 00286 00287 if (DEBUG>1) 00288 LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%", 00289 ring_free(rbuf)*100.0/rbuf->size); 00290 return rr; 00291 } 00292 00293 00294 00295 int ring_read_file(ringbuffer *rbuf, int fd, int count) 00296 { 00297 00298 int avail, pos, rest, rr; 00299 00300 if (count <=0 ) return -1; 00301 pos = rbuf->read_pos; 00302 rest = rbuf->size - pos; 00303 avail = ring_avail(rbuf); 00304 00305 if ( avail < count ){ 00306 #if 0 00307 if (DEBUG) 00308 LOG(VB_GENERAL, LOG_ERR, 00309 "ringbuffer underflow %d<%d %d %d", 00310 avail, count, pos, rbuf->write_pos); 00311 #endif 00312 return EMPTY_BUFFER; 00313 } 00314 00315 if (count >= rest){ 00316 rr = write (fd, rbuf->buffer+pos, rest); 00317 if (rr == rest && count - rest) 00318 rr += write (fd, rbuf->buffer, count - rest); 00319 if (rr >=0) 00320 rbuf->read_pos = (pos + rr) % rbuf->size; 00321 } else { 00322 rr = write (fd, rbuf->buffer+pos, count); 00323 if (rr >=0) 00324 rbuf->read_pos += rr; 00325 } 00326 00327 00328 if (DEBUG>1) 00329 LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%", 00330 ring_free(rbuf)*100.0/rbuf->size); 00331 return rr; 00332 } 00333 00334 00335 static void show(uint8_t *buf, int length) 00336 { 00337 int i,j,r; 00338 uint8_t temp[8]; 00339 uint8_t buffer[100]; 00340 buffer[0] = '\0'; 00341 00342 for (i=0; i<length; i+=16){ 00343 for (j=0; j < 8 && j+i<length; j++) 00344 { 00345 sprintf(temp, "0x%02x ", (int)(buf[i+j])); 00346 strcat(buffer, temp); 00347 } 00348 for (r=j; r<8; r++) 00349 strcat(buffer, " "); 00350 00351 strcat(buffer," "); 00352 00353 for (j=8; j < 16 && j+i<length; j++) 00354 { 00355 sprintf(temp, "0x%02x ", (int)(buf[i+j])); 00356 strcat(buffer, temp); 00357 } 00358 for (r=j; r<16; r++) 00359 strcat(buffer, " "); 00360 00361 for (j=0; j < 16 && j+i<length; j++){ 00362 switch(buf[i+j]){ 00363 case '0'...'Z': 00364 case 'a'...'z': 00365 sprintf(temp, "%c", buf[i+j]); 00366 break; 00367 default: 00368 sprintf(temp, "."); 00369 } 00370 strcat(buffer, temp); 00371 } 00372 LOG(VB_GENERAL, LOG_INFO, buffer); 00373 } 00374 } 00375 00376 void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off) 00377 { 00378 00379 unsigned int avail, pos, rest; 00380 00381 if (off+count > rbuf->size || off+count >ring_avail(rbuf)) 00382 return; 00383 pos = (rbuf->read_pos+off)%rbuf->size; 00384 rest = rbuf->size - pos ; 00385 avail = ring_avail(rbuf); 00386 00387 00388 if ( avail < count ){ 00389 #if 0 00390 if (DEBUG) 00391 LOG(VB_GENERAL, LOG_ERR, 00392 "ringbuffer peek underflow %d<%d %d %d\n", 00393 avail, count, pos, rbuf->write_pos); 00394 #endif 00395 return; 00396 } 00397 00398 if ( count < rest ){ 00399 show(rbuf->buffer+pos, count); 00400 } else { 00401 show(rbuf->buffer+pos, rest); 00402 if ( count - rest) 00403 show(rbuf->buffer, count - rest); 00404 } 00405 } 00406 00407 00408 int dummy_init(dummy_buffer *dbuf, int s) 00409 { 00410 dbuf->size = s; 00411 dbuf->fill = 0; 00412 if (ring_init(&dbuf->time_index, DBUF_INDEX*sizeof(uint64_t)) < 0) 00413 return -1; 00414 if (ring_init(&dbuf->data_index, DBUF_INDEX*sizeof(int32_t)) < 0) 00415 return -1; 00416 00417 return 0; 00418 } 00419 00420 void dummy_destroy(dummy_buffer *dbuf) 00421 { 00422 ring_destroy(&dbuf->time_index); 00423 ring_destroy(&dbuf->data_index); 00424 } 00425 00426 void dummy_clear(dummy_buffer *dbuf) 00427 { 00428 dbuf->fill = 0; 00429 ring_clear(&dbuf->time_index); 00430 ring_clear(&dbuf->data_index); 00431 } 00432 00433 int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size) 00434 { 00435 if (dummy_space(dbuf) < size) return -1; 00436 #if 0 00437 LOG(VB_GENERAL, LOG_INFO, "add %d ", dummy_space(dbuf)); 00438 #endif 00439 dbuf->fill += size; 00440 if (ring_write(&dbuf->time_index, (uint8_t *)&time, sizeof(uint64_t)) < 0) 00441 return -2; 00442 if (ring_write(&dbuf->data_index, (uint8_t *)&size, sizeof(uint32_t)) < 0) 00443 return -3; 00444 #if 0 00445 LOG(VB_GENERAL, LOG_INFO, " - %d = "%d", size, dummy_space(dbuf)); 00446 #endif 00447 return size; 00448 } 00449 00450 int dummy_delete(dummy_buffer *dbuf, uint64_t time) 00451 { 00452 uint64_t rtime; 00453 uint32_t size; 00454 int ex=0; 00455 uint32_t dsize=0; 00456 00457 do { 00458 if (ring_peek(&dbuf->time_index,(uint8_t *) &rtime, 00459 sizeof(uint64_t), 0)<0){ 00460 if (dsize) break; 00461 else return -1; 00462 } 00463 if (ptscmp(rtime,time) < 0){ 00464 ring_read(&dbuf->time_index,(uint8_t *) &rtime, 00465 sizeof(uint64_t)); 00466 ring_read(&dbuf->data_index,(uint8_t *) &size, 00467 sizeof(uint32_t)); 00468 dsize += size; 00469 } else ex = 1; 00470 } while (!ex); 00471 #if 0 00472 LOG(VB_GENERAL, LOG_INFO, "delete %d ", dummy_space(dbuf)); 00473 #endif 00474 dbuf->fill -= dsize; 00475 #if 0 00476 LOG(VB_GENERAL, LOG_INFO, " + %d = %d", dsize, dummy_space(dbuf)); 00477 #endif 00478 00479 return dsize; 00480 } 00481 00482 static void dummy_print(dummy_buffer *dbuf) 00483 { 00484 int i; 00485 uint64_t rtime; 00486 uint32_t size; 00487 int avail = ring_avail(&dbuf->time_index) / sizeof(uint64_t); 00488 for(i = 0; i < avail; i++) { 00489 ring_peek(&dbuf->time_index,(uint8_t *) &rtime, 00490 sizeof(uint64_t), i * sizeof(uint64_t)); 00491 ring_peek(&dbuf->data_index,(uint8_t *) &size, 00492 sizeof(uint32_t), i * sizeof(uint32_t)); 00493 00494 LOG(VB_GENERAL, LOG_INFO, "%d : %llu %u", i, 00495 (long long unsigned int)rtime, size); 00496 } 00497 LOG(VB_GENERAL, LOG_INFO, "Used: %d Free: %d data-free: %d", avail, 00498 1000-avail, dbuf->size - dbuf->fill); 00499 }
1.7.6.1