Ticket #1532: vlc-http-seek.patch
| File vlc-http-seek.patch, 11.8 kB (added by docbill, 5 months ago) |
|---|
-
a/modules/access/http.c
old new 58 58 static int Open ( vlc_object_t * ); 59 59 static void Close( vlc_object_t * ); 60 60 61 /* 62 * The minimum amount of data to read in a single request. This should be 63 * on the order of 60ms worth of data for medium quality 480p divx video. 64 */ 65 #define HTTP_MIN_BLOCKSIZE 0x4000L 66 /* 67 * The maximum amount of data to read in a 'fast seek' request. 68 * This corresponds to about half a second of medium quality 69 * 480p divx video. 70 */ 71 #define HTTP_SEEK_BLOCKSIZE 0x20000L 72 /* 73 * The maximum amount of data to read in a single request. This corresponds 74 * to about 8 seconds medium quality 480p divx video. 75 */ 76 #define HTTP_MAX_BLOCKSIZE 0x200000L 77 61 78 #define PROXY_TEXT N_("HTTP proxy") 62 79 #define PROXY_LONGTEXT N_( \ 63 80 "HTTP proxy to be used It must be of the form " \ … … 178 195 char *psz_icy_genre; 179 196 char *psz_icy_title; 180 197 181 int i_remaining; 198 int64_t i_remaining; 199 int64_t i_blocksize; 182 200 183 201 bool b_seekable; 184 202 bool b_reconnect; … … 195 213 static ssize_t Read( access_t *, uint8_t *, size_t ); 196 214 static ssize_t ReadCompressed( access_t *, uint8_t *, size_t ); 197 215 static int Seek( access_t *, int64_t ); 216 static int SkipForward( access_t *, int64_t ); 198 217 static int Control( access_t *, int, va_list ); 199 218 200 219 /* */ … … 268 287 p_sys->psz_icy_genre = NULL; 269 288 p_sys->psz_icy_title = NULL; 270 289 p_sys->i_remaining = 0; 271 290 p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE; 272 291 p_sys->cookies = saved_cookies; 273 292 274 293 /* Parse URI - remove spaces */ … … 588 607 } 589 608 590 609 if( p_access->info.i_size > 0 && 591 i_len + p_access->info.i_pos >p_access->info.i_size )610 (int64_t)(i_len + p_access->info.i_pos) > (int64_t)p_access->info.i_size ) 592 611 { 593 612 if( ( i_len = p_access->info.i_size - p_access->info.i_pos ) == 0 ) 594 613 { … … 626 645 } 627 646 } 628 647 629 if( i_len > p_sys->i_chunk )648 if( (int64_t)i_len > p_sys->i_chunk ) 630 649 { 631 i_len = p_sys->i_chunk;650 i_len = (size_t)p_sys->i_chunk; 632 651 } 633 652 } 634 653 635 if( p_sys->b_continuous && (ssize_t)i_len > p_sys->i_remaining ) 654 if(i_len <= 0) { 655 return 0; 656 } 657 if ( ! p_sys->b_continuous ) { 658 if(p_sys->i_remaining == 0) { 659 if ( Request( p_access, p_access->info.i_pos) != VLC_SUCCESS) { 660 int64_t i_pos = p_access->info.i_pos; 661 Disconnect( p_access ); 662 if ( Connect( p_access, i_pos ) ) { 663 p_access->info.b_eof = true; 664 return 0; 665 } 666 } 667 } 668 if( ((int64_t)i_len > p_sys->i_remaining) && (p_sys->i_remaining > 0) ) { 669 i_len = (size_t)p_sys->i_remaining; 670 } 671 } 672 if( p_sys->b_continuous && (p_sys->i_remaining > 0 ) && ((int64_t)i_len > p_sys->i_remaining) ) 636 673 { 637 674 /* Only ask for the remaining length */ 638 675 int i_new_len = p_sys->i_remaining; 639 676 if( i_new_len == 0 ) 640 677 { 641 Request( p_access, 0 ); 642 i_read = Read( p_access, p_buffer, i_len ); 643 return i_read; 678 //bcr this makes no sense 679 //bcr Request( p_access, 0 ); 680 //bcr i_read = Read( p_access, p_buffer, i_len ); 681 //bcr return i_read; 682 return 0; 644 683 } 645 684 i_len = i_new_len; 646 685 } … … 658 697 return -1; 659 698 } 660 699 } 661 if( i_len > i_next )662 i_len = i_next;700 if( (int64_t)i_len > i_next ) 701 i_len = (size_t)i_next; 663 702 } 664 703 665 704 i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, p_buffer, i_len, false ); … … 713 752 if( i_read == 0 ) p_access->info.b_eof = true; 714 753 } 715 754 716 if( p_sys->b_continuous ) 717 { 718 p_sys->i_remaining -= i_read; 719 } 755 p_sys->i_remaining -= i_read; 720 756 721 757 return i_read; 722 758 } … … 822 858 #endif 823 859 824 860 /***************************************************************************** 825 * Seek: close and re-open a connection at the right place 861 * SkipForward: Position ourself forward by i_len bytes by reading and if 862 * neccessary submitting an new request. 863 *****************************************************************************/ 864 static int SkipForward( access_t *p_access, int64_t i_len ) { 865 access_sys_t *p_sys = p_access->p_sys; 866 int64_t i_tell = p_access->info.i_pos + i_len; 867 if(p_sys->i_remaining > 0 ) { 868 size_t j_len = (size_t)((i_len > p_sys->i_remaining)?p_sys->i_remaining:i_len); 869 uint8_t *p_buffer = (uint8_t *)malloc(j_len); 870 do { 871 ssize_t i_read = Read(p_access, p_buffer, j_len); 872 if (i_read == 0 || i_read == (ssize_t)(-1)) { 873 free(p_buffer); 874 return VLC_EGENERIC; 875 } 876 j_len -= i_read; 877 } while ( j_len > 0); 878 free(p_buffer); 879 } 880 if(i_tell == p_access->info.i_pos) { 881 return VLC_SUCCESS; 882 } 883 p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE; 884 return Request( p_access, i_tell); 885 } 886 887 /***************************************************************************** 888 * Seek: Attempt to seek by a small read or offseting the position of the 889 * next block. If that fails close and re-open a connection at the right place. 826 890 *****************************************************************************/ 827 891 static int Seek( access_t *p_access, int64_t i_pos ) 828 892 { 829 msg_Dbg( p_access, "trying to seek to %"PRId64 , i_pos);893 msg_Dbg( p_access, "trying to seek to %"PRId64"/"PRId64, i_pos, p_access->info.i_size ); 830 894 895 if( i_pos < 0 ) 896 { 897 msg_Err( p_access, "seeking too early" ); 898 return Seek( p_access, 0); 899 } 900 if( i_pos > p_access->info.i_size ) 901 { 902 msg_Err( p_access, "seeking too far" ); 903 // Fix me: This replicates the file.c behavior of returning 904 // success even when seeking too far. 905 return Seek( p_access, p_access->info.i_size ); 906 } 907 // we can use the skip data to seek forward 908 access_sys_t *p_sys = p_access->p_sys; 909 if( i_pos > p_access->info.i_pos) { 910 int64_t i_needed = i_pos - p_access->info.i_pos; 911 if( (i_needed <= HTTP_SEEK_BLOCKSIZE)||(p_sys->i_remaining <= HTTP_SEEK_BLOCKSIZE) ) { 912 SkipForward(p_access, i_needed ); 913 } 914 } 915 if ( i_pos == p_access->info.i_pos ) { 916 return VLC_SUCCESS; 917 } 918 // Now we try skipping the remaining bytes and then making the next 919 // request with our desired offset. 920 if( (p_sys->i_remaining > 0) && (p_sys->i_remaining <= HTTP_SEEK_BLOCKSIZE)) { 921 if ( SkipForward( p_access, p_sys->i_remaining) == VLC_SUCCESS ) { 922 p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE; 923 if (Request(p_access, i_pos) == VLC_SUCCESS) { 924 return VLC_SUCCESS; 925 } 926 } 927 } 928 // Since the server does not have to honour our keep-alive request 929 // we could end-up here. 831 930 Disconnect( p_access ); 832 833 if ( Connect( p_access, i_pos ))931 int retval= Connect( p_access, i_pos ); 932 if (retval != VLC_SUCCESS ) 834 933 { 835 934 msg_Err( p_access, "seek failed" ); 836 935 p_access->info.b_eof = true; 837 return VLC_EGENERIC;838 936 } 839 return VLC_SUCCESS;937 return retval; 840 938 } 841 939 842 940 /***************************************************************************** … … 859 957 break; 860 958 case ACCESS_CAN_FASTSEEK: 861 959 pb_bool = (bool*)va_arg( args, bool* ); 862 *pb_bool = false; 960 // http 1.1 should be just as fast as nfs... 961 *pb_bool = p_sys->b_seekable; 863 962 break; 864 963 case ACCESS_CAN_PAUSE: 865 964 case ACCESS_CAN_CONTROL_PACE: … … 945 1044 p_sys->psz_icy_name = NULL; 946 1045 p_sys->psz_icy_genre = NULL; 947 1046 p_sys->psz_icy_title = NULL; 1047 p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE; 948 1048 949 1049 p_access->info.i_size = 0; 950 1050 p_access->info.i_pos = i_tell; … … 1086 1186 /* User Agent */ 1087 1187 net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "User-Agent: %s\r\n", 1088 1188 p_sys->psz_user_agent ); 1189 p_access->info.i_pos = i_tell; 1089 1190 /* Offset */ 1090 1191 if( p_sys->i_version == 1 ) 1091 1192 { 1193 int64_t i_end=i_tell+(int64_t)(p_sys->i_blocksize-1); 1194 if((p_access->info.i_size > 0) && (i_end >= p_access->info.i_size)) { 1195 i_end = p_access->info.i_size-1; 1196 } 1197 else if ((p_sys->i_blocksize *= 2) > HTTP_MAX_BLOCKSIZE) { 1198 p_sys->i_blocksize = HTTP_MAX_BLOCKSIZE; 1199 } 1092 1200 net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, 1093 "Range: bytes=%"PRId64"- \r\n", i_tell);1201 "Range: bytes=%"PRId64"-%"PRId64"\r\n", i_tell, i_end ); 1094 1202 } 1095 1203 1096 1204 /* Cookies */ … … 1131 1239 net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Icy-MetaData: 1\r\n" ); 1132 1240 1133 1241 1134 if( p_sys->b_continuous ) 1135 { 1136 net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs, 1242 net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs, 1137 1243 "Connection: Keep-Alive\r\n" ); 1138 }1139 else if( p_sys->i_version == 1 )1140 {1141 net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs,1142 "Connection: Close\r\n");1143 }1144 1244 1145 1245 if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "\r\n" ) < 0 ) 1146 1246 { … … 1196 1296 } 1197 1297 free( psz ); 1198 1298 1299 p_sys->i_remaining = 0; 1199 1300 for( ;; ) 1200 1301 { 1201 1302 char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, pvs ); … … 1236 1337 p_access->info.i_size = -1; 1237 1338 msg_Dbg( p_access, "this frame size=%lld", atoll(p ) ); 1238 1339 p_sys->i_remaining = atoll( p ); 1340 p_access->info.i_pos = 0; 1239 1341 } 1240 1342 else 1241 1343 { 1242 p_access->info.i_size = i_tell + atoll( p ); 1243 msg_Dbg( p_access, "stream size=%"PRId64, p_access->info.i_size ); 1344 p_access->info.i_pos = i_tell; 1345 p_sys->i_remaining = atoll( p ); 1346 if(p_access->info.i_size <= 0) { 1347 p_access->info.i_size = i_tell + p_sys->i_remaining; 1348 msg_Dbg( p_access, "stream size=%"PRId64, p_access->info.i_size ); 1349 } 1244 1350 } 1245 1351 } 1352 else if(! strcasecmp( psz, "Content-Range") ) { 1353 int64_t j_tell = i_tell; 1354 int64_t j_end = (i_tell + p_sys->i_remaining - 1); 1355 int64_t j_size = p_access->info.i_size; 1356 sscanf(p,"bytes %"PRId64"-%"PRId64"/%"PRId64,&j_tell,&j_end,&j_size); 1357 p_access->info.i_size = j_size; 1358 p_access->info.i_pos = j_tell; 1359 p_sys->i_remaining = j_end+1-j_tell; 1360 msg_Dbg( p_access, "stream size=%"PRId64",position=%"PRId64",remaining=%"PRId64,j_size,j_tell,p_sys->i_remaining); 1361 } 1246 1362 else if( !strcasecmp( psz, "Location" ) ) 1247 1363 { 1248 1364 char * psz_new_loc;
