Search code examples
javaandroidhttp-live-streamingexoplayer

How to get observed bitrate from Google's ExoPlayer


I'm playing an HLS file using ExoPlayer and i'm trying to get the actual observed bitrate (not the indicated bitrate).

I now there is the onInFoListener interface but documentation is sketchy, can anyone help?


Solution

  • After doing research i came up with this:

    Indeed ExoPlayer comes with a InfoListener interface that can be used for this purpose. This is the code i wrote.

    (in my implementation mVideoPlayer is the var name that holds my ExoPlayer instance)

    on the code that prepares the player...

       ...
       // assigns this as InfoListener for ExoPlayer
       mVideoPlayer.setInfoListener(this);
       ...
    

    Later on the InfoListener implementation ...

        private long mBytesLoaded = 0;
        private long mBytesLoadedSeconds = 0;
        private long mLastBytesLoadedTime = 0;
    
        @Override
        public void onLoadStarted(int sourceId, long length, int type, int trigger, Format format, int mediaStartTimeMs, int mediaEndTimeMs) {
            Log.d(TAG, "onLoadStarted sourceId " + sourceId + " length " + length + " type " + type + " format " + format + " mediaStartTimeMs " + mediaStartTimeMs + " mediaEndTimeMs " + mediaEndTimeMs);
            if(mLastBytesLoadedTime == 0) mLastBytesLoadedTime = System.currentTimeMillis();
        }
    
        @Override
        public void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format, int mediaStartTimeMs, int mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs) {
            Log.d(TAG, "onLoadCompleted sourceId " + sourceId + " bytesLoaded " + bytesLoaded + " type " + type + " format " + format + " mediaStartTimeMs " + mediaStartTimeMs + " mediaEndTimeMs " + mediaEndTimeMs);
    
            // log... logBytesLoadedInSeconds
            long now = System.currentTimeMillis();
            float diffInSeconds = (now - mLastBytesLoadedTime) / 1000;
            this.logBytesLoadedInSeconds(bytesLoaded, diffInSeconds); // helper function, explain bellow
            mLastBytesLoadedTime = now;
        }
    

    This is that helper function that is logging how many bytes are loaded in an amount of seconds

        /**
         * Logs an amount of bytes loaded in an amount of seconds
         *
         * @param bytes amount of bytes loaded
         * @param seconds time in seconds that it took to load those bytes
         */
        private void logBytesLoadedInSeconds(long bytes, float seconds){
            mBytesLoaded += bytes;
            mBytesLoadedSeconds += seconds;
            if(mBytesLoadedSeconds > 0){
                double bytesPerSecond = mBytesLoaded / mBytesLoadedSeconds;
                double bitsPerSecond = bytesPerSecond * 8; // (8 bits in a byte)
                if(bitsPerSecond < mIndicatedBitrate){
                    // buffer is falling behind!
                    mBufferWarned = true;
                }else{
                    if(mBufferWarned){
                        // buffer caught up
                    }
                }
            }
        }
    

    Finally, we can use all of this information to get an estimate of the observed birate...

        public int getObservedBitrate(){
            if(mBytesLoadedSeconds != 0){
                double bytesPerSecond = mBytesLoaded / mBytesLoadedSeconds;
                double bitsPerSecond = bytesPerSecond * 8; // (8 bits in a byte)
                Log.d(TAG," mBytesLoaded " + mBytesLoaded + " in "+mBytesLoadedSeconds+" seconds ("+(int)bitsPerSecond+" b/s indicated "+mIndicatedBitrate+" b/s) ");
                return (int)bitsPerSecond;
            }
            return 0;
        }