Beispiel #1
0
static void
rtp_session_fill_cb(gpointer unused_data, gpointer session_p)
{
    RTP_session *rtp_s = (RTP_session*)session_p;
    Resource *resource = rtp_s->track->parent;
    BufferQueue_Consumer *consumer = rtp_s->consumer;
    gulong unseen;

	unseen = bq_consumer_unseen(consumer);
	if (unseen >= MAX_RND_PACKAGES)
		return;

    while ((unseen = bq_consumer_unseen(consumer)) < 3*MAX_RND_PACKAGES)
    {
    	if (r_read(resource) != RESOURCE_OK)
            break;
    }
}
Beispiel #2
0
/**
 * @brief Callback for the queue filling for the resource
 *
 * @param consumer_p A generic pointer to the consumer for non-live queues
 * @param resource_p A generic pointer to the resource to fill the queue of
 *
 * This function takes care of reading the data from the demuxer (via
 * @ref Demuxer::read_packet); it will executed repeatedly until
 * either the resources ends (@ref Resource::eor becomes non-zero),
 * the thread is requested to stop (@ref Resource::fill_pool becomes
 * NULL), or, for non-live resources only, when the @ref consumer_p
 * queue is long enough for the client to receive data.
 *
 * @note For live streams, the @ref consume_p pointer should have the
 *       value -1 to indicate that it shouldn't be used.
 *
 * @note This function will lock the @ref Resource::lock mutex
 *       (repeatedly).
 */
static void r_read_cb(gpointer consumer_p, gpointer resource_p)
{
    Resource *resource = (Resource*)resource_p;
    BufferQueue_Consumer *consumer = (BufferQueue_Consumer*)consumer_p;
    const gboolean live = resource->demuxer->source == LIVE_SOURCE;
    const gulong buffered_frames = feng_srv.buffered_frames;

    g_assert( (live && consumer == GINT_TO_POINTER(-1)) || (!live && consumer != GINT_TO_POINTER(-1)) );

    do {
        /* setting this to NULL with an atomic, non-locking operation
           is our "stop" signal. */
        if ( g_atomic_pointer_get(&resource->fill_pool) == NULL )
            return;

        /* Only check for enough buffered frames if we're not doing
           live; otherwise keep on filling; we also assume that
           consumer will be NULL in that case. */
        if ( !live && bq_consumer_unseen(consumer) >= buffered_frames )
            return;

        //        fprintf(stderr, "r_read_cb(%p)\n", resource);

        g_mutex_lock(resource->lock);
        switch( resource->demuxer->read_packet(resource) ) {
        case RESOURCE_OK:
            break;
        case RESOURCE_EOF:
            xlog(LOG_INF,
                    "r_read_unlocked: %s read_packet() end of file.",
                    resource->mrl);
            resource->eor = true;
            break;
        default:
            xlog(LOG_FAT,
                    "r_read_unlocked: %s read_packet() error.",
                    resource->mrl);
            resource->eor = true;
            break;
        }
        g_mutex_unlock(resource->lock);
    } while ( g_atomic_int_get(&resource->eor) == 0 );
}
Beispiel #3
0
/**
 * @brief Do the work of filling an RTP session with data
 *
 * @param unued_data Unused
 * @param session_p The session parameter from rtp_session_fill
 *
 *
 * @internal This function is used to initialize @ref
 *           RTP_session::fill_pool.
 */
static void rtp_session_fill_cb(ATTR_UNUSED gpointer unused_data,
                                gpointer session_p)
{
    RTP_session *session = (RTP_session*)session_p;
    Resource *resource = session->track->parent;
    BufferQueue_Consumer *consumer = session->consumer;
    gulong unseen;
    const gulong buffered_frames = resource->srv->srvconf.buffered_frames;

    while ( (unseen = bq_consumer_unseen(consumer)) < buffered_frames ) {
#if 0
        fprintf(stderr, "calling read_packet from %p for %p[%s] (%u/%d)\n",
                session,
                resource, resource->info->mrl,
                unseen, buffered_frames);
#endif

        if ( r_read(resource) != RESOURCE_OK )
            break;
    }
}
Beispiel #4
0
/**
 * 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);
}