void free_stream(stream_t *s){ // printf("\n*** free_stream() called ***\n"); #ifdef CONFIG_STREAM_CACHE cache_uninit(s); #endif if (s->capture_file) { fclose(s->capture_file); s->capture_file = NULL; } if(s->close) s->close(s); if(s->fd>0){ /* on unix we define closesocket to close on windows however we have to distinguish between network socket and file */ if(s->url && strstr(s->url,"://")) closesocket(s->fd); else close(s->fd); } #if HAVE_WINSOCK2_H mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 uninit\n"); WSACleanup(); // there might be a better place for this (-> later) #endif // Disabled atm, i don't like that. s->priv can be anything after all // streams should destroy their priv on close //free(s->priv); free(s->url); free(s); }
/** * \return 1 on success, 0 if the function was interrupted and -1 on error */ int stream_enable_cache(stream_t *stream,int size,int min,int seek_limit){ int ss = stream->sector_size ? stream->sector_size : STREAM_BUFFER_SIZE; int res = -1; cache_vars_t* s; if (stream->flags & STREAM_NON_CACHEABLE) { mp_msg(MSGT_CACHE,MSGL_STATUS,"\rThis stream is non-cacheable\n"); return 1; } s=cache_init(size,ss); if(s == NULL) return -1; stream->cache_data=s; s->stream=stream; // callback s->seek_limit=seek_limit; //make sure that we won't wait from cache_fill //more data than it is allowed to fill if (s->seek_limit > s->buffer_size - s->fill_limit ){ s->seek_limit = s->buffer_size - s->fill_limit; } if (min > s->buffer_size - s->fill_limit) { min = s->buffer_size - s->fill_limit; } // to make sure we wait for the cache process/thread to be active // before continuing if (min <= 0) min = 1; #if FORKED_CACHE if((stream->cache_pid=fork())){ if ((pid_t)stream->cache_pid == -1) stream->cache_pid = 0; #else { stream_t* stream2=malloc(sizeof(stream_t)); memcpy(stream2,s->stream,sizeof(stream_t)); s->stream=stream2; #if defined(__MINGW32__) stream->cache_pid = _beginthread( ThreadProc, 0, s ); #elif defined(__OS2__) stream->cache_pid = _beginthread( ThreadProc, NULL, 256 * 1024, s ); #else { pthread_t tid; pthread_create(&tid, NULL, ThreadProc, s); stream->cache_pid = 1; } #endif #endif if (!stream->cache_pid) { mp_msg(MSGT_CACHE, MSGL_ERR, "Starting cache process/thread failed: %s.\n", strerror(errno)); goto err_out; } // wait until cache is filled at least prefill_init % /* mp_msg(MSGT_CACHE,MSGL_V,"CACHE_PRE_INIT: %"PRId64" [%"PRId64"] %"PRId64" pre:%d eof:%d \n", (int64_t)s->min_filepos,(int64_t)s->read_filepos,(int64_t)s->max_filepos,min,s->eof);*/ while(s->read_filepos<s->min_filepos || s->max_filepos-s->read_filepos<min){ /* mp_msg(MSGT_CACHE,MSGL_STATUS,MSGTR_CacheFill, 100.0*(float)(s->max_filepos-s->read_filepos)/(float)(s->buffer_size), (int64_t)s->max_filepos-s->read_filepos );*/ if(s->eof) break; // file is smaller than prefill size if(stream_check_interrupt(PREFILL_SLEEP_TIME)) { res = 0; goto err_out; } } //mp_msg(MSGT_CACHE,MSGL_STATUS,"\n"); return 1; // parent exits err_out: cache_uninit(stream); return res; } #if FORKED_CACHE signal(SIGTERM,exit_sighandler); // kill cache_mainloop(s); // make sure forked code never leaves this function exit(0); #endif } #if !FORKED_CACHE #if defined(__MINGW32__) || defined(__OS2__) static void ThreadProc( void *s ){ cache_mainloop(s); _endthread(); }
/** * \return 1 on success, 0 if the function was interrupted and -1 on error */ int stream_enable_cache(stream_t *stream,int size,int min,int seek_limit){ int ss = stream->sector_size ? stream->sector_size : STREAM_BUFFER_SIZE; int res = -1; cache_vars_t* s; if (stream->flags & STREAM_NON_CACHEABLE) { mp_msg(MSGT_CACHE,MSGL_STATUS,"\rThis stream is non-cacheable\n"); return 1; } s=cache_init(size,ss); if(s == NULL) return -1; stream->cache_data=s; s->stream=stream; // callback s->seek_limit=seek_limit; //make sure that we won't wait from cache_fill //more data than it is alowed to fill if (s->seek_limit > s->buffer_size - s->fill_limit ){ s->seek_limit = s->buffer_size - s->fill_limit; } if (min > s->buffer_size - s->fill_limit) { min = s->buffer_size - s->fill_limit; } #if !defined(__MINGW32__) && !defined(PTHREAD_CACHE) && !defined(__OS2__) if((stream->cache_pid=fork())){ if ((pid_t)stream->cache_pid == -1) stream->cache_pid = 0; #else { stream_t* stream2=malloc(sizeof(stream_t)); memcpy(stream2,s->stream,sizeof(stream_t)); s->stream=stream2; #if defined(__MINGW32__) stream->cache_pid = _beginthread( ThreadProc, 0, s ); #elif defined(__OS2__) stream->cache_pid = _beginthread( ThreadProc, NULL, 256 * 1024, s ); #else { pthread_t tid; pthread_create(&tid, NULL, ThreadProc, s); stream->cache_pid = 1; } #endif #endif if (!stream->cache_pid) { mp_msg(MSGT_CACHE, MSGL_ERR, "Starting cache process/thread failed: %s.\n", strerror(errno)); goto err_out; } // wait until cache is filled at least prefill_init % mp_msg(MSGT_CACHE,MSGL_V,"CACHE_PRE_INIT: %"PRId64" [%"PRId64"] %"PRId64" pre:%d eof:%d \n", (int64_t)s->min_filepos,(int64_t)s->read_filepos,(int64_t)s->max_filepos,min,s->eof); while(s->read_filepos<s->min_filepos || s->max_filepos-s->read_filepos<min){ mp_msg(MSGT_CACHE,MSGL_STATUS,MSGTR_CacheFill, 100.0*(float)(s->max_filepos-s->read_filepos)/(float)(s->buffer_size), (int64_t)s->max_filepos-s->read_filepos ); if(s->eof) break; // file is smaller than prefill size if(stream_check_interrupt(PREFILL_SLEEP_TIME)) { res = 0; goto err_out; } } mp_msg(MSGT_CACHE,MSGL_STATUS,"\n"); return 1; // parent exits err_out: cache_uninit(stream); return res; } #if defined(__MINGW32__) || defined(PTHREAD_CACHE) || defined(__OS2__) } #ifdef PTHREAD_CACHE static void *ThreadProc( void *s ){ #else static void ThreadProc( void *s ){ #endif #endif #ifdef CONFIG_GUI use_gui = 0; // mp_msg may not use gui stuff in forked code #endif // cache thread mainloop: signal(SIGTERM,exit_sighandler); // kill do { if(!cache_fill(s)){ usec_sleep(FILL_USLEEP_TIME); // idle } // cache_stats(s->cache_data); } while (cache_execute_control(s)); #if defined(__MINGW32__) || defined(__OS2__) _endthread(); #elif defined(PTHREAD_CACHE) return NULL; #else // make sure forked code never leaves this function exit(0); #endif } int cache_stream_fill_buffer(stream_t *s){ int len; if(s->eof){ s->buf_pos=s->buf_len=0; return 0; } if(!s->cache_pid) return stream_fill_buffer(s); // cache_stats(s->cache_data); if(s->pos!=((cache_vars_t*)s->cache_data)->read_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"!!! read_filepos differs!!! report this bug...\n"); len=cache_read(s->cache_data,s->buffer, ((cache_vars_t*)s->cache_data)->sector_size); //printf("cache_stream_fill_buffer->read -> %d\n",len); if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; } s->buf_pos=0; s->buf_len=len; s->pos+=len; // printf("[%d]",len);fflush(stdout); return len; }