📄 timeshift.c
字号:
msleep( 10000 ); continue; } p_sys->i_data += p_block->i_buffer; /* Write block */ if( !p_sys->p_write_list && !p_sys->p_read_list && block_FifoSize( p_sys->p_fifo ) < TIMESHIFT_FIFO_MAX ) { /* If there isn't too much timeshifted data, * write directly to FIFO */ block_FifoPut( p_sys->p_fifo, p_block ); continue; } WriteBlockToFile( p_access, p_block ); block_Release( p_block ); /* Read from file to fill up the fifo */ while( block_FifoSize( p_sys->p_fifo ) < TIMESHIFT_FIFO_MIN && vlc_object_alive (p_access) ) { p_block = ReadBlockFromFile( p_access ); if( !p_block ) break; block_FifoPut( p_sys->p_fifo, p_block ); } } msg_Dbg( p_access, "timeshift: no more input data" ); while( vlc_object_alive (p_access) && (p_sys->p_read_list || block_FifoSize( p_sys->p_fifo ) ) ) { /* Read from file to fill up the fifo */ while( block_FifoSize( p_sys->p_fifo ) < TIMESHIFT_FIFO_MIN && vlc_object_alive (p_access) && p_sys->p_read_list ) { p_block = ReadBlockFromFile( p_access ); if( !p_block ) break; block_FifoPut( p_sys->p_fifo, p_block ); } msleep( 100000 ); } msg_Dbg( p_access, "timeshift: EOF" ); p_src->info.b_eof = true; /* Send dummy packet to avoid deadlock in Block() */ block_FifoPut( p_sys->p_fifo, block_New( p_access, 0 ) ); return NULL;}/***************************************************************************** * NextFileWrite: *****************************************************************************/static void NextFileWrite( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; ts_entry_t *p_next; if( !p_sys->p_write_list ) { p_sys->i_write_size = 0; return; } p_next = p_sys->p_write_list->p_next; /* Put written file in read list */ if( p_sys->i_write_size < p_sys->i_file_size ) ftruncate( fileno( p_sys->p_write_list->file ), p_sys->i_write_size ); fseek( p_sys->p_write_list->file, 0, SEEK_SET ); *p_sys->pp_read_last = p_sys->p_write_list; p_sys->pp_read_last = &p_sys->p_write_list->p_next; p_sys->p_write_list->p_next = 0; /* Switch to next file to write */ p_sys->p_write_list = p_next; if( !p_sys->p_write_list ) p_sys->pp_write_last = &p_sys->p_write_list; p_sys->i_write_size = 0;}/***************************************************************************** * NextFileRead: *****************************************************************************/static void NextFileRead( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; ts_entry_t *p_next; if( !p_sys->p_read_list ) return; p_next = p_sys->p_read_list->p_next; /* Put read file in write list */ fseek( p_sys->p_read_list->file, 0, SEEK_SET ); *p_sys->pp_write_last = p_sys->p_read_list; p_sys->pp_write_last = &p_sys->p_read_list->p_next; p_sys->p_read_list->p_next = 0; /* Switch to next file to read */ p_sys->p_read_list = p_next; if( !p_sys->p_read_list ) p_sys->pp_read_last = &p_sys->p_read_list;}/***************************************************************************** * WriteBlockToFile: *****************************************************************************/static int WriteBlockToFile( access_t *p_access, block_t *p_block ){ access_sys_t *p_sys = p_access->p_sys; int i_write, i_buffer; if( p_sys->i_write_size == p_sys->i_file_size ) NextFileWrite( p_access ); /* Open new file if necessary */ if( !p_sys->p_write_list ) { FILE *file; sprintf( p_sys->psz_filename, "%s%u.dat", p_sys->psz_filename_base, p_sys->i_files ); file = utf8_fopen( p_sys->psz_filename, "w+b" ); if( !file && p_sys->i_files < 2 ) { /* We just can't work with less than 2 buffer files */ msg_Err( p_access, "cannot open temporary file '%s' (%m)", p_sys->psz_filename ); return VLC_EGENERIC; } else if( !file ) return VLC_EGENERIC; p_sys->p_write_list = malloc( sizeof(ts_entry_t) ); p_sys->p_write_list->p_next = 0; p_sys->p_write_list->file = file; p_sys->pp_write_last = &p_sys->p_write_list->p_next; p_sys->i_files++; } /* Write to file */ i_buffer = __MIN( p_block->i_buffer, p_sys->i_file_size - p_sys->i_write_size ); i_write = fwrite( p_block->p_buffer, 1, i_buffer, p_sys->p_write_list->file ); if( i_write > 0 ) p_sys->i_write_size += i_write; //p_access->info.i_size += i_write; //p_access->info.i_update |= INPUT_UPDATE_SIZE; if( i_write < i_buffer ) { /* Looks like we're short of space */ if( !p_sys->p_write_list->p_next ) { msg_Warn( p_access, "no more space, overwritting old data" ); NextFileRead( p_access ); NextFileRead( p_access ); } /* Make sure we switch to next file in write list */ p_sys->i_write_size = p_sys->i_file_size; } p_block->p_buffer += i_write; p_block->i_buffer -= i_write; /* Check if we have some data left */ if( p_block->i_buffer ) return WriteBlockToFile( p_access, p_block ); return VLC_SUCCESS;}/***************************************************************************** * ReadBlockFromFile: *****************************************************************************/static block_t *ReadBlockFromFile( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; block_t *p_block; if( !p_sys->p_read_list && p_sys->p_write_list ) { /* Force switching to next write file, that should * give us something to read */ NextFileWrite( p_access ); } if( !p_sys->p_read_list ) return 0; p_block = block_New( p_access, 4096 ); p_block->i_buffer = fread( p_block->p_buffer, 1, 4096, p_sys->p_read_list->file ); if( p_block->i_buffer == 0 ) NextFileRead( p_access ); //p_access->info.i_size -= p_block->i_buffer; //p_access->info.i_update |= INPUT_UPDATE_SIZE; return p_block;}/***************************************************************************** * Seek: seek to a specific location in a file *****************************************************************************/static int Seek( access_t *p_access, int64_t i_pos ){ //access_sys_t *p_sys = p_access->p_sys; (void)p_access; (void)i_pos; return VLC_SUCCESS;}/***************************************************************************** * *****************************************************************************/static int Control( access_t *p_access, int i_query, va_list args ){ bool *pb_bool; int *pi_int; switch( i_query ) { case ACCESS_CAN_SEEK: case ACCESS_CAN_FASTSEEK: pb_bool = (bool*)va_arg( args, bool* ); *pb_bool = true; break; case ACCESS_CAN_CONTROL_PACE: /* Not really true */ case ACCESS_CAN_PAUSE: pb_bool = (bool*)va_arg( args, bool* ); *pb_bool = true; break; case ACCESS_GET_MTU: pi_int = (int*)va_arg( args, int * ); *pi_int = 0; break; case ACCESS_SET_PAUSE_STATE: break; /* Forward everything else to the source access */ default: return access_vaControl( p_access->p_source, i_query, args ); } return VLC_SUCCESS;}/***************************************************************************** * GetTmpFilePath: *****************************************************************************/#ifdef WIN32#define getpid() (int)GetCurrentProcessId()#endifstatic char *GetTmpFilePath( access_t *p_access ){ char *psz_dir = var_GetNonEmptyString( p_access, "timeshift-dir" ); char *psz_filename_base; if( psz_dir == NULL ) {#ifdef WIN32 DWORD ret = GetTempPathW (0, NULL); wchar_t wdir[ret + 3]; // can at least old "C:" + nul const wchar_t *pwdir = wdir; wchar_t *pwdir_free = NULL; if (GetTempPathW (ret + 1, wdir) == 0) { pwdir_free = pwdir = _wgetcwd (NULL, 0); if (pwdir == NULL) pwdir = L"C:"; } psz_dir = FromWide (pwdir); if (pwdir_free != NULL) free (pwdir_free); /* remove trailing antislash if any */ if (psz_dir[strlen (psz_dir) - 1] == '\\') psz_dir[strlen (psz_dir) - 1] = '\0';#else psz_dir = strdup( "/tmp" );#endif } if( asprintf( &psz_filename_base, "%s/vlc-timeshift-%d-%d-", psz_dir, getpid(), p_access->i_object_id ) == -1 ) psz_filename_base = NULL; free( psz_dir ); return psz_filename_base;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -