Changeset 5df2e973d079c0a43572cb9b248d226911b4cfbc
- Timestamp:
- 06/05/08 19:18:50 (3 months ago)
- git-parent:
- Files:
-
- src/input/stream.c (modified) (16 diffs)
- src/libvlc-module.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
src/input/stream.c
rd666030 r5df2e97 28 28 #include <vlc_common.h> 29 29 30 #include <assert.h> 31 30 32 #include "input_internal.h" 31 33 … … 33 35 34 36 /* TODO: 35 * - tune the 2 methods 37 * - tune the 2 methods (block/stream) 36 38 * - compute cost for seek 37 39 * - improve stream mode seeking with closest segments 38 40 * - ... 41 * - Maybe remove (block/stream) in favour of immediate 39 42 */ 40 43 … … 44 47 * - using pf_read 45 48 * More complex scheme using mutliple track to avoid seeking 49 * - using directly the access (only indirection for peeking). 50 * This method is known to introduce much less latency. 51 * It should probably defaulted (instead of the stream method (2)). 46 52 */ 47 53 … … 102 108 } access_entry_t; 103 109 110 typedef enum stream_read_method_t 111 { 112 Immediate, 113 Block, 114 Stream 115 } stream_read_method_t; 116 104 117 struct stream_sys_t 105 118 { 106 119 access_t *p_access; 107 120 108 bool b_block; /* Block method (1) or stream*/121 stream_read_method_t method; /* method to use */ 109 122 110 123 int64_t i_pos; /* Current reading offset */ … … 138 151 139 152 } stream; 153 154 /* Method 3: for pf_read */ 155 struct 156 { 157 int64_t i_end; 158 uint8_t *p_buffer; 159 } immediate; 140 160 141 161 /* Peek temporary buffer */ … … 183 203 static int AReadStream( stream_t *s, void *p_read, int i_read ); 184 204 205 /* Method 3 */ 206 static int AStreamReadImmediate( stream_t *s, void *p_read, int i_read ); 207 static int AStreamPeekImmediate( stream_t *s, const uint8_t **pp_peek, int i_read ); 208 static int AStreamSeekImmediate( stream_t *s, int64_t i_pos ); 209 185 210 /* Common */ 186 211 static int AStreamControl( stream_t *s, int i_query, va_list ); … … 189 214 static int ASeek( stream_t *s, int64_t i_pos ); 190 215 216 /**************************************************************************** 217 * Method 3 helpers: 218 ****************************************************************************/ 219 220 static inline int64_t stream_buffered_size( stream_t *s ) 221 { 222 return s->p_sys->immediate.i_end; 223 } 224 225 static inline void stream_buffer_empty( stream_t *s, int length ) 226 { 227 length = __MAX( stream_buffered_size( s ), length ); 228 if( length ) 229 { 230 memmove( s->p_sys->immediate.p_buffer, 231 s->p_sys->immediate.p_buffer + length, 232 stream_buffered_size( s ) - length ); 233 } 234 s->p_sys->immediate.i_end -= length; 235 } 236 237 static inline void stream_buffer_fill( stream_t *s, int length ) 238 { 239 s->p_sys->immediate.i_end += length; 240 } 241 242 static inline uint8_t * stream_buffer( stream_t *s ) 243 { 244 return s->p_sys->immediate.p_buffer; 245 } 191 246 192 247 /**************************************************************************** … … 255 310 /* Common field */ 256 311 p_sys->p_access = p_access; 257 p_sys->b_block = p_access->pf_block ? true : false; 312 if( p_access->pf_block ) 313 p_sys->method = Block; 314 else if (var_CreateGetBool( s, "use-stream-immediate")) 315 p_sys->method = Immediate; 316 else 317 p_sys->method = Stream; 318 258 319 p_sys->i_pos = p_access->info.i_pos; 259 320 … … 341 402 p_sys->p_peek = NULL; 342 403 343 if( p_sys->b_block ) 344 { 404 if( p_sys->method == Block ) 405 { 406 msg_Dbg( s, "Using AStream*Block" ); 345 407 s->pf_read = AStreamReadBlock; 346 408 s->pf_peek = AStreamPeekBlock; … … 363 425 } 364 426 } 365 else 427 else if (p_sys->method == Immediate) 428 { 429 msg_Dbg( s, "Using AStream*Immediate" ); 430 431 s->pf_read = AStreamReadImmediate; 432 s->pf_peek = AStreamPeekImmediate; 433 434 /* Allocate/Setup our tracks (useful to peek)*/ 435 p_sys->immediate.i_end = 0; 436 p_sys->immediate.p_buffer = malloc( STREAM_CACHE_SIZE ); 437 438 msg_Dbg( s, "p_buffer %p-%p", p_sys->immediate.p_buffer, 439 p_sys->immediate.p_buffer + STREAM_CACHE_SIZE ); 440 441 if( p_sys->immediate.p_buffer == NULL ) 442 { 443 msg_Err( s, "Out of memory when allocating stream cache (%d bytes)", 444 STREAM_CACHE_SIZE ); 445 goto error; 446 } 447 } 448 else /* ( p_sys->method == Stream ) */ 366 449 { 367 450 int i; 451 452 msg_Dbg( s, "Using AStream*Stream" ); 368 453 369 454 s->pf_read = AStreamReadStream; … … 410 495 411 496 error: 412 if( p_sys-> b_block )497 if( p_sys->method == Block ) 413 498 { 414 499 /* Nothing yet */ … … 437 522 vlc_object_detach( s ); 438 523 439 if( p_sys-> b_block ) block_ChainRelease( p_sys->block.p_first );524 if( p_sys->method == Block ) block_ChainRelease( p_sys->block.p_first ); 440 525 else free( p_sys->stream.p_buffer ); 441 526 … … 474 559 p_sys->i_pos = p_sys->p_access->info.i_pos; 475 560 476 if( p_sys-> b_block )561 if( p_sys->method == Block ) 477 562 { 478 563 block_ChainRelease( p_sys->block.p_first ); … … 489 574 AStreamPrebufferBlock( s ); 490 575 } 491 else 576 else if( p_sys->method == Immediate ) 577 { 578 stream_buffer_empty( s, stream_buffered_size( s ) ); 579 } 580 else /* ( p_sys->method == Stream ) */ 492 581 { 493 582 int i; … … 573 662 case STREAM_SET_POSITION: 574 663 i_64 = (int64_t)va_arg( args, int64_t ); 575 if( p_sys-> b_block )664 if( p_sys->method == Block ) 576 665 return AStreamSeekBlock( s, i_64 ); 577 else 666 else if( p_sys->method == Immediate ) 667 return AStreamSeekImmediate( s, i_64 ); 668 else /* ( p_sys->method == Stream ) */ 578 669 return AStreamSeekStream( s, i_64 ); 579 670 … … 1421 1512 } 1422 1513 1514 /**************************************************************************** 1515 * Method 3: 1516 ****************************************************************************/ 1517 1518 static int AStreamReadImmediate( stream_t *s, void *p_read, int i_read ) 1519 { 1520 stream_sys_t *p_sys = s->p_sys; 1521 1522 #ifdef STREAM_DEBUG 1523 msg_Dbg( s, "AStreamReadImmediate p_read=%p i_read=%d", 1524 p_read, i_read ); 1525 #endif 1526 1527 if( p_read == NULL ) 1528 { 1529 /* seek within this stream if possible, else use plain old read and discard */ 1530 stream_sys_t *p_sys = s->p_sys; 1531 access_t *p_access = p_sys->p_access; 1532 bool b_aseek; 1533 access_Control( p_access, ACCESS_CAN_SEEK, &b_aseek ); 1534 if( b_aseek ) 1535 return AStreamSeekStream( s, p_sys->i_pos + i_read ) ? 0 : i_read; 1536 } 1537 1538 /* First, check if we already have some data in the buffer, 1539 * that we could copy directly */ 1540 int i_copy = __MIN( stream_buffered_size( s ), i_read ); 1541 if( i_copy ) 1542 { 1543 #ifdef STREAM_DEBUG 1544 msg_Dbg( s, "AStreamReadImmediate: copy %d from %p", i_copy, stream_buffer( s ) ); 1545 #endif 1546 1547 assert( i_copy <= STREAM_CACHE_SIZE ); 1548 1549 if( p_read ) 1550 { 1551 memcpy( p_read, stream_buffer( s ), i_copy ); 1552 p_read = (uint8_t *)p_read + i_copy; 1553 } 1554 } 1555 1556 /* Now that we've read our buffer we don't need its i_copy bytes */ 1557 stream_buffer_empty( s, i_copy ); 1558 1559 /* Now check if we have still to really read some data */ 1560 int i_to_read = i_read - i_copy; 1561 if( i_to_read ) 1562 { 1563 i_to_read = AReadStream( s, p_read, i_to_read ); 1564 } 1565 1566 p_sys->i_pos += i_to_read; 1567 1568 return i_to_read + i_copy; 1569 } 1570 1571 static int AStreamPeekImmediate( stream_t *s, const uint8_t **pp_peek, int i_read ) 1572 { 1573 #ifdef STREAM_DEBUG 1574 msg_Dbg( s, "AStreamPeekImmediate: %d size=%"PRId64, 1575 i_read, size_buffered_size( s ) ); 1576 #endif 1577 1578 /* Avoid problem, but that shouldn't happen */ 1579 if( i_read > STREAM_CACHE_SIZE / 2 ) 1580 i_read = STREAM_CACHE_SIZE / 2; 1581 1582 int i_to_read = i_read - stream_buffered_size( s ); 1583 if( i_to_read > 0 ) 1584 { 1585 #ifdef STREAM_DEBUG 1586 msg_Dbg( s, "AStreamPeekImmediate: Reading %d", 1587 i_to_read ); 1588 #endif 1589 i_to_read = AReadStream( s, stream_buffer( s ) + stream_buffered_size( s ), 1590 i_to_read ); 1591 1592 if( i_to_read > 0 ) 1593 stream_buffer_fill( s, i_to_read ); 1594 } 1595 1596 *pp_peek = stream_buffer( s ); 1597 1598 return __MIN(stream_buffered_size( s ), i_read); 1599 } 1600 1601 static int AStreamSeekImmediate( stream_t *s, int64_t i_pos ) 1602 { 1603 stream_sys_t *p_sys = s->p_sys; 1604 access_t *p_access = p_sys->p_access; 1605 bool b_aseek; 1606 1607 #ifdef STREAM_DEBUG 1608 msg_Dbg( s, "AStreamSeekImmediate to %"PRId64" pos=%"PRId64 1609 i_pos, p_sys->i_pos ); 1610 #endif 1611 1612 access_Control( p_access, ACCESS_CAN_SEEK, &b_aseek ); 1613 if( !b_aseek ) 1614 { 1615 /* We can't do nothing */ 1616 msg_Dbg( s, "AStreamSeekImmediate: can't seek" ); 1617 return VLC_EGENERIC; 1618 } 1619 1620 /* Just reset our buffer */ 1621 stream_buffer_empty( s, stream_buffered_size( s ) ); 1622 1623 if( ASeek( s, i_pos ) ) return VLC_EGENERIC; 1624 1625 return VLC_SUCCESS; 1626 } 1423 1627 1424 1628 /**************************************************************************** src/libvlc-module.c
r04f2e3a r5df2e97 994 994 "This option minimizes the number of threads needed to run VLC.") 995 995 996 #define USE_STREAM_IMMEDIATE N_("(Experimental) Use the StreamImmediate " \ 997 "method and minimize the caching done at the access level.") 998 #define USE_STREAM_IMMEDIATE_LONGTEXT N_( \ 999 "This option is useful if you want to lower the latency when " \ 1000 "reading a stream") 1001 996 1002 #define PLUGIN_PATH_TEXT N_("Modules search path") 997 1003 #define PLUGIN_PATH_LONGTEXT N_( \ … … 1814 1820 MINIMIZE_THREADS_LONGTEXT, true ); 1815 1821 change_need_restart(); 1822 1823 add_bool( "use-stream-immediate", false, NULL, 1824 USE_STREAM_IMMEDIATE, USE_STREAM_IMMEDIATE_LONGTEXT, false ); 1816 1825 1817 1826 #if !defined(__APPLE__) && !defined(SYS_BEOS) && defined(LIBVLC_USE_PTHREAD)
