/* Read access */ static ssize_t AStreamReadStream(stream_t *s, void *buf, size_t len) { stream_sys_t *sys = s->p_sys; input_thread_t *input = s->p_input; ssize_t val = 0; do { if (vlc_access_Eof(sys->access)) return 0; if (vlc_killed()) return -1; val = vlc_access_Read(sys->access, buf, len); if (val == 0) return 0; /* EOF */ } while (val < 0); if (input != NULL) { uint64_t total; vlc_mutex_lock(&input->p->counters.counters_lock); stats_Update(input->p->counters.p_read_bytes, val, &total); stats_Update(input->p->counters.p_input_bitrate, total, NULL); stats_Update(input->p->counters.p_read_packets, 1, NULL); vlc_mutex_unlock(&input->p->counters.counters_lock); } return val; }
ssize_t vlc_tls_Write(vlc_tls_t *session, const void *buf, size_t len) { struct pollfd ufd; ufd.fd = session->fd; ufd.events = POLLOUT; for (size_t sent = 0;;) { if (vlc_killed()) { errno = EINTR; return -1; } ssize_t val = session->send(session, buf, len); if (val > 0) { buf = ((const char *)buf) + val; len -= val; sent += val; } if (len == 0 || val == 0) return sent; if (val == -1 && errno != EINTR && errno != EAGAIN) return sent ? (ssize_t)sent : -1; vlc_poll_i11e(&ufd, 1, -1); } }
ssize_t vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall) { struct pollfd ufd; ufd.fd = session->fd; ufd.events = POLLIN; for (size_t rcvd = 0;;) { if (vlc_killed()) { errno = EINTR; return -1; } ssize_t val = session->recv(session, buf, len); if (val > 0) { if (!waitall) return val; buf = ((char *)buf) + val; len -= val; rcvd += val; } if (len == 0 || val == 0) return rcvd; if (val == -1 && errno != EINTR && errno != EAGAIN) return rcvd ? (ssize_t)rcvd : -1; vlc_poll_i11e(&ufd, 1, -1); } }
static ssize_t stream_ReadRaw(stream_t *s, void *buf, size_t len) { stream_priv_t *priv = (stream_priv_t *)s; size_t copy = 0; ssize_t ret = 0; while (len > 0) { if (vlc_killed()) { ret = -1; break; } ret = s->pf_read(s, buf, len); if (ret <= 0) break; assert((size_t)ret <= len); if (buf != NULL) buf = (unsigned char *)buf + ret; len -= ret; copy += ret; priv->offset += ret; } return (copy > 0) ? (ssize_t)copy : ret; }
static int AStreamRefillStream(stream_t *s) { stream_sys_t *sys = s->p_sys; stream_track_t *tk = &sys->tk[sys->i_tk]; /* We read but won't increase i_start after initial start + offset */ int i_toread = __MIN(sys->i_used, STREAM_CACHE_TRACK_SIZE - (tk->i_end - tk->i_start - sys->i_offset)); if (i_toread <= 0) return VLC_SUCCESS; /* EOF */ #ifdef STREAM_DEBUG msg_Dbg(s, "AStreamRefillStream: used=%d toread=%d", sys->i_used, i_toread); #endif mtime_t start = mdate(); while (i_toread > 0) { int i_off = tk->i_end % STREAM_CACHE_TRACK_SIZE; int i_read; if (vlc_killed()) return VLC_EGENERIC; i_read = __MIN(i_toread, STREAM_CACHE_TRACK_SIZE - i_off); i_read = stream_Read(s->p_source, &tk->p_buffer[i_off], i_read); /* msg_Dbg(s, "AStreamRefillStream: read=%d", i_read); */ if (i_read < 0) { continue; } else if (i_read == 0) return VLC_SUCCESS; /* Update end */ tk->i_end += i_read; /* Windows of STREAM_CACHE_TRACK_SIZE */ if (tk->i_start + STREAM_CACHE_TRACK_SIZE < tk->i_end) { unsigned i_invalid = tk->i_end - tk->i_start - STREAM_CACHE_TRACK_SIZE; tk->i_start += i_invalid; sys->i_offset -= i_invalid; } i_toread -= i_read; sys->i_used -= i_read; sys->stat.i_bytes += i_read; sys->stat.i_read_count++; } sys->stat.i_read_time += mdate() - start; return VLC_SUCCESS; }
static int UrlInterruptCallback(void *access) { /* NOTE: This works so long as libavformat invokes the callback from the * same thread that invokes libavformat. Currently libavformat does not * create internal threads at all. This is not proper event handling in any * case; libavformat needs fixing. */ (void) access; return vlc_killed(); }
static void AStreamPrebufferStream(stream_t *s) { stream_sys_t *sys = s->p_sys; mtime_t start = mdate(); bool first = true; msg_Dbg(s, "starting pre-buffering"); for (;;) { stream_track_t *tk = &sys->tk[sys->i_tk]; mtime_t now = mdate(); int i_read; int i_buffered = tk->i_end - tk->i_start; if (vlc_killed() || i_buffered >= STREAM_CACHE_PREBUFFER_SIZE) { int64_t i_byterate; /* Update stat */ sys->stat.i_bytes = i_buffered; sys->stat.i_read_time = now - start; i_byterate = (CLOCK_FREQ * sys->stat.i_bytes) / (sys->stat.i_read_time+1); msg_Dbg(s, "pre-buffering done %"PRId64" bytes in %"PRId64"s - " "%"PRId64" KiB/s", sys->stat.i_bytes, sys->stat.i_read_time / CLOCK_FREQ, i_byterate / 1024); break; } i_read = STREAM_CACHE_TRACK_SIZE - i_buffered; i_read = __MIN((int)sys->i_read_size, i_read); i_read = stream_Read(s->p_source, &tk->p_buffer[i_buffered], i_read); if (i_read < 0) continue; else if (i_read == 0) break; /* EOF */ if (first) { msg_Dbg(s, "received first data after %"PRId64" ms", (mdate() - start) / 1000); first = false; } tk->i_end += i_read; sys->stat.i_read_count++; } }
/* Block access */ static ssize_t AStreamReadBlock(stream_t *s, void *buf, size_t len) { stream_sys_t *sys = s->p_sys; input_thread_t *input = s->p_input; block_t *block = sys->block; while (block == NULL) { if (vlc_access_Eof(sys->access)) return 0; if (vlc_killed()) return -1; block = vlc_access_Block(sys->access); } if (input != NULL) { uint64_t total; vlc_mutex_lock(&input->p->counters.counters_lock); stats_Update(input->p->counters.p_read_bytes, block->i_buffer, &total); stats_Update(input->p->counters.p_input_bitrate, total, NULL); stats_Update(input->p->counters.p_read_packets, 1, NULL); vlc_mutex_unlock(&input->p->counters.counters_lock); } size_t copy = block->i_buffer < len ? block->i_buffer : len; if (likely(copy > 0) && buf != NULL /* skipping data? */) memcpy(buf, block->p_buffer, copy); block->p_buffer += copy; block->i_buffer -= copy; if (block->i_buffer == 0) { block_Release(block); sys->block = NULL; } else sys->block = block; return copy; }
static int ScanReadCallback( scan_t *p_scan, void *p_privdata, unsigned i_probe_timeout, size_t i_packets_max, uint8_t *p_packet, size_t *pi_count ) { access_t *p_access = (access_t *) p_privdata; access_sys_t *p_sys = p_access->p_sys; *pi_count = 0; /* Initialize file descriptor sets */ struct pollfd ufds[2]; ufds[0].fd = p_sys->dvb.i_handle; ufds[0].events = POLLIN; ufds[1].fd = p_sys->dvb.i_frontend_handle; ufds[1].events = POLLPRI; frontend_status_t status; FrontendGetStatus( &p_sys->dvb, &status ); bool b_has_lock = status.b_has_lock; mtime_t i_scan_start = mdate(); for( ; *pi_count == 0; ) { /* Find if some data is available */ int i_ret; mtime_t i_timeout = b_has_lock ? i_probe_timeout: DVB_SCAN_MAX_LOCK_TIME; do { mtime_t i_poll_timeout = i_scan_start - mdate() + i_timeout; i_ret = 0; if( vlc_killed() || scan_IsCancelled( p_scan ) ) break; if( i_poll_timeout >= 0 ) i_ret = vlc_poll_i11e( ufds, 2, i_poll_timeout / 1000 ); } while( i_ret < 0 && errno == EINTR ); if( i_ret < 0 ) { return VLC_EGENERIC; } else if( i_ret == 0 ) { return VLC_ENOITEM; } if( ufds[1].revents ) { FrontendPoll( VLC_OBJECT(p_access), &p_sys->dvb ); FrontendGetStatus( &p_sys->dvb, &status ); if( status.b_has_lock && !b_has_lock ) { i_scan_start = mdate(); b_has_lock = true; } } if ( ufds[0].revents ) { ssize_t i_read = read( p_sys->dvb.i_handle, p_packet, TS_PACKET_SIZE * i_packets_max ); if( i_read < 0 ) { msg_Warn( p_access, "read failed: %s", vlc_strerror_c(errno) ); break; } else { *pi_count = i_read / TS_PACKET_SIZE; } } } return VLC_SUCCESS; }
/* Access part */ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, const char* psz_browser_flag_, const char* psz_filter_, const char* psz_requested_count_, const char* psz_sort_criteria_ ) { IXML_Document* p_action = NULL; IXML_Document* p_response = NULL; Upnp_i11e_cb *i11eCb = NULL; access_sys_t *sys = (access_sys_t *)m_access->p_sys; int i_res; if ( vlc_killed() ) return NULL; i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "ObjectID", psz_object_id_ ? psz_object_id_ : "0" ); if ( i_res != UPNP_E_SUCCESS ) { msg_Dbg( m_access, "AddToAction 'ObjectID' failed: %s", UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; } i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "BrowseFlag", psz_browser_flag_ ); if ( i_res != UPNP_E_SUCCESS ) { msg_Dbg( m_access, "AddToAction 'BrowseFlag' failed: %s", UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; } i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "Filter", psz_filter_ ); if ( i_res != UPNP_E_SUCCESS ) { msg_Dbg( m_access, "AddToAction 'Filter' failed: %s", UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; } i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "StartingIndex", "0" ); if ( i_res != UPNP_E_SUCCESS ) { msg_Dbg( m_access, "AddToAction 'StartingIndex' failed: %s", UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; } i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "RequestedCount", psz_requested_count_ ); if ( i_res != UPNP_E_SUCCESS ) { msg_Dbg( m_access, "AddToAction 'RequestedCount' failed: %s", UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; } i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "SortCriteria", psz_sort_criteria_ ); if ( i_res != UPNP_E_SUCCESS ) { msg_Dbg( m_access, "AddToAction 'SortCriteria' failed: %s", UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; } /* Setup an interruptible callback that will call sendActionCb if not * interrupted by vlc_interrupt_kill */ i11eCb = new Upnp_i11e_cb( sendActionCb, &p_response ); i_res = UpnpSendActionAsync( sys->p_upnp->handle(), m_psz_root, CONTENT_DIRECTORY_SERVICE_TYPE, NULL, /* ignored in SDK, must be NULL */ p_action, Upnp_i11e_cb::run, i11eCb ); if ( i_res != UPNP_E_SUCCESS ) { msg_Err( m_access, "%s when trying the send() action with URL: %s", UpnpGetErrorMessage( i_res ), m_access->psz_location ); } /* Wait for the callback to fill p_response or wait for an interrupt */ i11eCb->waitAndRelease(); browseActionCleanup: ixmlDocument_free( p_action ); return p_response; }