/** * @brief Resume (or start) an RTP session * * @param session_gen The session to resume or start * @param range_gen Pointer tp @ref RTSP_Range to start with * * @todo This function should probably take care of starting eventual * libev events when the scheduler is replaced. * * This function is used by the PLAY method of RTSP to start or resume * a session; since a newly-created session starts as paused, this is * the only method available. * * The use of a pointer to double rather than a double itself is to * make it possible to pass this function straight to foreach * functions from glib. * * @internal This function should only be called from g_slist_foreach. */ static void rtp_session_resume(gpointer session_gen, gpointer range_gen) { RTP_session *session = (RTP_session*)session_gen; RTSP_Range *range = (RTSP_Range*)range_gen; fnc_log(FNC_LOG_VERBOSE, "Resuming session %p\n", session); session->range = range; session->start_seq = 1 + session->seq_no; session->start_rtptime = g_random_int(); session->send_time = 0.0; session->last_packet_send_time = time(NULL); /* Create the new thread pool for the read requests */ session->fill_pool = g_thread_pool_new(rtp_session_fill_cb, session, 1, true, NULL); /* Prefetch frames */ rtp_session_fill(session); ev_periodic_set(&session->transport.rtp_writer, range->playback_time - 0.05, 0, NULL); ev_periodic_start(session->srv->loop, &session->transport.rtp_writer); ev_io_start(session->srv->loop, &session->transport.rtcp_reader); }
void start_time_redraw_tick(struct ev_loop* main_loop) { if (time_redraw_tick) { ev_periodic_set(time_redraw_tick, 0., 1.0, 0); ev_periodic_again(main_loop, time_redraw_tick); } else { if (!(time_redraw_tick = calloc(sizeof(struct ev_periodic), 1))) { return; } ev_periodic_init(time_redraw_tick, time_redraw_cb, 0., 1., 0); ev_periodic_start(main_loop, time_redraw_tick); } }
void flux_periodic_watcher_reset (flux_watcher_t *w, double next, double interval, flux_reschedule_f reschedule_cb) { struct f_periodic *fp = w->impl; struct ev_loop *loop = w->r->loop; assert (w->signature == PERIODIC_SIG); fp->reschedule_cb = reschedule_cb; ev_periodic_set (&fp->evp, next, interval, reschedule_cb ? periodic_reschedule_cb : NULL); ev_periodic_again (loop, &fp->evp); }
/* SchedulerType.tp_new */ static PyObject * Scheduler_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { Scheduler *self = (Scheduler *)PeriodicBaseType.tp_new(type, args, kwargs); if (!self) { return NULL; } self->prepare.data = (void *)self; ev_prepare_init(&self->prepare, stop_scheduler_Scheduler); ev_periodic_set(&((PeriodicBase *)self)->periodic, 0.0, 0.0, scheduler_Scheduler); return (PyObject *)self; }
void start_time_redraw_tick(struct ev_loop* main_loop) { if (time_redraw_tick) { ev_periodic_set(time_redraw_tick, 1.0, 60., 0); ev_periodic_again(main_loop, time_redraw_tick); } else { /* When there is no memory, we just don’t have a timeout. We cannot * exit() here, since that would effectively unlock the screen. */ if (!(time_redraw_tick = calloc(sizeof(struct ev_periodic), 1))) return; ev_periodic_init(time_redraw_tick,time_redraw_cb, 1.0, 60., 0); ev_periodic_start(main_loop, time_redraw_tick); } }
/* SchedulerType.tp_new */ static PyObject * Scheduler_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { Scheduler *self = (Scheduler *)PeriodicBaseType.tp_new(type, args, kwargs); if (!self) { return NULL; } self->prepare = PyMem_Malloc(sizeof(ev_prepare)); if (!self->prepare) { PyErr_NoMemory(); Py_DECREF(self); return NULL; } ev_prepare_init(self->prepare, Scheduler_Stop); self->prepare->data = self; ev_periodic_set((ev_periodic *)((Watcher *)self)->watcher, 0.0, 0.0, Scheduler_Schedule); return (PyObject *)self; }
/** * Send pending RTP packets to a session. * * @param loop eventloop * @param w contains the session the RTP session for which to send the packets * @todo implement a saner ratecontrol */ static void rtp_write_cb(struct ev_loop *loop, ev_periodic *w, ATTR_UNUSED int revents) { RTP_session *session = w->data; Resource *resource = session->track->parent; MParserBuffer *buffer = NULL; ev_tstamp next_time = w->offset; #ifdef HAVE_METADATA if (session->metadata) cpd_send(session, now); #endif /* If there is no buffer, it means that either the producer * has been stopped (as we reached the end of stream) or that * there is no data for the consumer to read. If that's the * case we just give control back to the main loop for now. */ if ( bq_consumer_stopped(session->consumer) ) { /* If the producer has been stopped, we send the * finishing packets and go away. */ fnc_log(FNC_LOG_INFO, "[rtp] Stream Finished"); rtcp_send_sr(session, BYE); return; } /* Check whether we have enough extra frames to send. If we have * no extra frames we have a problem, since we're going to send * one packet at least. */ if (resource->eor) fnc_log(FNC_LOG_INFO, "[%s] end of resource %d packets to be fetched", session->track->properties.encoding_name, bq_consumer_unseen(session->consumer)); /* Get the current buffer, if there is enough data */ if ( !(buffer = bq_consumer_get(session->consumer)) ) { /* We wait a bit of time to get the data but before it is * expired. */ if (resource->eor) { fnc_log(FNC_LOG_INFO, "[rtp] Stream Finished"); rtcp_send_sr(session, BYE); return; } next_time += 0.01; // assumed to be enough } else { MParserBuffer *next; double delivery = buffer->delivery; double timestamp = buffer->timestamp; double duration = buffer->duration; gboolean marker = buffer->marker; rtp_packet_send(session, buffer); if (session->pkt_count % 29 == 1) rtcp_send_sr(session, SDES); if (bq_consumer_move(session->consumer)) { next = bq_consumer_get(session->consumer); if(delivery != next->delivery) { if (session->track->properties.media_source == MS_live) next_time += next->delivery - delivery; else next_time = session->range->playback_time - session->range->begin_time + next->delivery; } } else { if (marker) next_time += duration; } fnc_log(FNC_LOG_VERBOSE, "[%s] Now: %5.4f, cur %5.4f[%5.4f][%5.4f], next %5.4f %s\n", session->track->properties.encoding_name, ev_now(loop) - session->range->playback_time, delivery, timestamp, duration, next_time - session->range->playback_time, marker? "M" : " "); } ev_periodic_set(w, next_time, 0, NULL); ev_periodic_again(loop, w); rtp_session_fill(session); }