All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.fmj.media.rtp.JitterBufferStats Maven / Gradle / Ivy

There is a newer version: 1.0.2-jitsi
Show newest version
package net.sf.fmj.media.rtp;

import java.awt.*;

import javax.media.*;
import javax.media.control.*;
import javax.media.protocol.*;
import javax.media.rtp.*;

import net.sf.fmj.media.*;
import net.sf.fmj.media.protocol.rtp.DataSource;

/**
 * Implements {@link PacketQueueControl} for {@link RTPSourceStream} and the
 * queue of RTP packets that it utilizes.
 *
 * @author Boris Grozev
 * @author Lyubomir Marinov
 * @author Tom Denham
 */
class JitterBufferStats
    implements JitterBufferControl
{
    /**
     * The number of RTP packets that the associated queue has discarded because
     * it was full.
     */
    private int discardedFull;

    /**
     * The number of RTP packets that the associated queue has discarded because
     * they arrived too late to be added to the queue. If the queue exhibits
     * adaptive behavior, it has taken into account the fact that the packets
     * in question have arrived too late.
     */
    private int discardedLate;

    /**
     * The number of RTP packets that the associated queue has discarded due to
     * resetting.
     */
    private int discardedReset;

    /**
     * The number of RTP packets that the associated queue has discarded while
     * shrinking.
     */
    private int discardedShrink;

    /**
     * The number of RTP packets that the associated queue has discarded because
     * they arrived too late to be added to the queue. If the queue exhibits
     * adaptive behavior, it has NOT (in contrast to {@link #discardedLate}
     * taken into account the fact that the packets in question have arrived too
     * late.
     */
    private int discardedVeryLate;

    /**
     * The maximum size/capacity in number of RTP packets that the associated
     * queue has ever reached.
     */
    private int maxSizeReached;

    private int nbAdd;

    private int nbGrow;

    private int nbReset;

    /**
     * An average approximation of the size in bytes of an RTP packet.
     */
    private int sizePerPacket;

    /**
     * The {@link RTPSourceStream} for which this instance implements
     * {@link PacketQueueControl}.
     */
    private final RTPSourceStream stream;

    /**
     * Initializes a new JitterBufferStats instance which is to
     * implement {@link PacketQueueControl} for a specific
     * {@link RTPSourceStream}.
     *
     * @param stream the RTPSourceStream for which the new instance is
     * to implement {@link PacketQueueControl}
     */
    JitterBufferStats(RTPSourceStream stream)
    {
        this.stream = stream;
    }

    /**
     * {@inheritDoc}
     *
     * Delegates to the JitterBufferBehaviour of the
     * RTPSourceStream.
     */
    @Override
    public int getAbsoluteMaximumDelay()
    {
        return stream.getBehaviour().getAbsoluteMaximumDelay();
    }

    /**
     * {@inheritDoc}
     *
     * The Control implementation of JitterBufferStats does
     * not provide any user interface of its own and, consequently, always
     * returns null.
     */
    public Component getControlComponent()
    {
        return null;
    }

    /**
     * {@inheritDoc}
     *
     * Warning: The implementation of JitterBufferStats does not
     * have a notion of packet duration and, consequently, it may be inaccurate.
     * The method {@link #getNominalDelay()} delegates to
     * JitterBufferBehaviour which is more likely to have a notion of
     * packet duration and, consequently, it likely to be more accurate.
     */
    public int getCurrentDelayMs()
    {
        // TODO Auto-generated method stub
        return getCurrentDelayPackets() * 20;
    }

    /**
     * {@inheritDoc}
     */
    public int getCurrentDelayPackets()
    {
        return getCurrentSizePackets() / 2;
    }

    /**
     * {@inheritDoc}
     */
    public int getCurrentPacketCount()
    {
        return stream.q.getFillCount();
    }

    /**
     * {@inheritDoc}
     */
    public int getCurrentSizePackets()
    {
        return stream.q.getCapacity();
    }

    /**
     * {@inheritDoc}
     *
     * Returns the sum of the values of the other discardedXXX
     * properties of this instance such as discardedFull,
     * discaredLate, discaredReset, etc.
     */
    public int getDiscarded()
    {
        return
            getDiscardedFull()
                + getDiscardedLate()
                + getDiscardedReset()
                + getDiscardedShrink()
                + getDiscardedVeryLate();
    }

    /**
     * {@inheritDoc}
     */
    public int getDiscardedFull()
    {
        return discardedFull;
    }

    /**
     * {@inheritDoc}
     */
    public int getDiscardedLate()
    {
        return discardedLate;
    }

    /**
     * {@inheritDoc}
     */
    public int getDiscardedReset()
    {
        return discardedReset;
    }

    /**
     * {@inheritDoc}
     */
    public int getDiscardedShrink()
    {
        return discardedShrink;
    }

    /**
     * {@inheritDoc}
     */
    public int getDiscardedVeryLate()
    {
        return discardedVeryLate;
    }

    /**
     * {@inheritDoc}
     *
     * Delegates to the JitterBufferBehaviour of the
     * RTPSourceStream.
     */
    @Override
    public int getMaximumDelay()
    {
        return stream.getBehaviour().getMaximumDelay();
    }

    /**
     * {@inheritDoc}
     */
    public int getMaxSizeReached()
    {
        return maxSizeReached;
    }

    int getNbAdd()
    {
        return nbAdd;
    }

    /**
     * {@inheritDoc}
     *
     * Delegates to the JitterBufferBehaviour of the
     * RTPSourceStream.
     */
    @Override
    public int getNominalDelay()
    {
        return stream.getBehaviour().getNominalDelay();
    }

    /**
     * Gets an average approximation of the size in bytes of an RTP packet.
     *
     * @return an average approximation of the size in bytes of an RTP packet
     */
    int getSizePerPacket()
    {
        return sizePerPacket;
    }

    /**
     * Increments the number of RTP packets that the associated queue has
     * discarded because it was full.
     */
    void incrementDiscardedFull()
    {
        discardedFull++;
        incrementRTPStatsPDUDrop();
    }

    /**
     * Increments the number of RTP packets that the associated queue has
     * discarded because they arrived too late to be added to the queue. If the
     * queue exhibits adaptive behavior, it has taken into account the fact that
     * the packets in question have arrived too late.
     */
    void incrementDiscardedLate()
    {
        discardedLate++;
        incrementRTPStatsPDUDrop();
    }

    /**
     * Increments the number of RTP packets that the associated queue has
     * discarded due to resetting.
     */
    void incrementDiscardedReset()
    {
        discardedReset++;
        incrementRTPStatsPDUDrop();
    }

    /**
     * Increments the number of RTP packets that the associated queue has
     * discarded while shrinking.
     */
    void incrementDiscardedShrink()
    {
        discardedShrink++;
        incrementRTPStatsPDUDrop();
    }

    /**
     * Increments the number of RTP packets that the associated queue has
     * discarded because they arrived too late to be added to the queue. If the
     * queue exhibits adaptive behavior, it has NOT (in contrast to
     * {@link #discardedLate} taken into account the fact that the packets in
     * question have arrived too late.
     */
    void incrementDiscardedVeryLate()
    {
        discardedVeryLate++;
        incrementRTPStatsPDUDrop();
    }

    void incrementNbAdd()
    {
        nbAdd++;
    }

    void incrementNbGrow()
    {
        nbGrow++;
    }

    void incrementNbReset()
    {
        nbReset++;
    }

    /**
     * Updates the {@link RTPStats#PDUDROP} of the RTPStats associated
     * with this JitterBufferStats because the two classes maintain
     * discard-related statistics and RTPStats provides them to the
     * public through the interface {@link ReceptionStats}.
     */
    private void incrementRTPStatsPDUDrop()
    {
        /*
         * There is no direct chain of references from JitterBufferStats to
         * RTPStats. Walk through an indirect chain of references then but be
         * careful. Start by making sure that the RTPSourceStream associated
         * with this JitterBufferStats is still associated with the DataSource
         * which initialized it.
         */
        DataSource datasource = stream.datasource;

        if (datasource != null)
        {
            PushBufferStream[] datasourceStreams = datasource.getStreams();

            if (datasourceStreams != null)
            {
                for (PushBufferStream datasourceStream : datasourceStreams)
                {
                    if (datasourceStream == stream)
                    {
                        /*
                         * The DataSource which initialized the RTPSourceStream
                         * associated with this JitterBufferStats is still
                         * associated with it. Continue by finding an SSRCInfo
                         * which is associated with the
                         * DataSource/RTPSourceStream i.e. this
                         * JitterBufferStats.
                         */
                        RTPSessionMgr mgr = datasource.getMgr();

                        if (mgr != null)
                        {
                            SSRCInfo ssrcinfo
                                = mgr.getSSRCInfo(datasource.getSSRC());

                            if ((ssrcinfo != null)
                                    && (ssrcinfo.dsource == datasource)
                                    && (ssrcinfo.dstream == stream))
                            {
                                /*
                                 * We've located the RTPStats associated with
                                 * this JitterBufferStats.
                                 */
                                RTPStats rtpstats = ssrcinfo.stats;

                                if (rtpstats != null)
                                    rtpstats.update(RTPStats.PDUDROP);
                            }
                        }
                        break;
                    }
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean isAdaptiveBufferEnabled()
    {
        return stream.getBehaviour().isAdaptive();
    }

    /**
     * Prints a human-readable representation of this instance using
     * {@link Log#info(Object)}.
     */
    void printStats()
    {
        String cn = RTPSourceStream.class.getName() + " ";

        Log.info(cn + "Total packets added: " + getNbAdd());
        Log.info(cn + "Times reset() called: " + nbReset);
        Log.info(cn + "Times grow() called: " + nbGrow);
        Log.info(cn + "Packets dropped because full: " + getDiscardedFull());
        Log.info(cn + "Packets dropped while shrinking: " + getDiscardedShrink());
        Log.info(cn + "Packets dropped because they were late: " + getDiscardedLate());
        Log.info(cn + "Packets dropped because they were late by more than MAX_SIZE: " + getDiscardedVeryLate());
        Log.info(cn + "Packets dropped in reset(): " + getDiscardedReset());
        Log.info(cn + "Max size reached: " + getMaxSizeReached());
        Log.info(cn + "Adaptive jitter buffer mode was " + (isAdaptiveBufferEnabled() ? "enabled" : "disabled"));
    }

    /**
     * Notifies this instance that the size/capacity of the associated queue of
     * RTP packets may have changed and that it may be time for this instance to
     * update the value to be returned by {@link #getMaxSizeReached()}.
     */
    void updateMaxSizeReached()
    {
        int size = getCurrentSizePackets();

        if (maxSizeReached < size)
            maxSizeReached = size;
    }

    /**
     * Updates the average approximation of the size in bytes of an RTP packet.
     *
     * @param buffer the Buffer which is to be taken into account for
     * the purposes of calculating and maintaining an average approximation of
     * the size in bytes of an RTP packet
     */
    void updateSizePerPacket(Buffer buffer)
    {
        int bufferLength = buffer.getLength();

        sizePerPacket
            = (sizePerPacket == 0)
                ? bufferLength
                : ((sizePerPacket + bufferLength) / 2);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy